     1                                  ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
     2                                  ; (re-write kernel for test by using previous version without a major defect)
     3                                  ; ****************************************************************************
     4                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.2.3
     5                                  ; ----------------------------------------------------------------------------
     6                                  ; NASM version 2.15 (unix386.s)
     7                                  ;
     8                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     9                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
    10                                  ;
    11                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    12                                  ; (v0.1 - Beginning: 11/07/2012)
    13                                  ;
    14                                  ; [ Last Modification: 16/07/2022 ]
    15                                  ;
    16                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    17                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    18                                  ; <Bell Laboratories (17/3/1972)>
    19                                  ; <Preliminary Release of UNIX Implementation Document>
    20                                  ;
    21                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    22                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    23                                  ;
    24                                  ; ****************************************************************************
    25                                  
    26                                  ; 24/12/2013
    27                                  
    28                                  ; Entering protected mode:
    29                                  ; Derived from 'simple_asm.txt' source code file and 
    30                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    31                                  ; (gregor.brunmar@home.se)
    32                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    33                                  ;
    34                                  
    35                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    36                                  ; by Michael Chourdakis (2009) 
    37                                  ; http://www.codeproject.com/Articles/45788/
    38                                  ; http://www.michaelchourdakis.com
    39                                  ;
    40                                  
    41                                  ; Global Descriptor Table:
    42                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    43                                  ; by Linus Torvalds (1991-1992)
    44                                  ;
    45                                  
    46                                  KLOAD	equ 10000h ; Kernel loading address
    47                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    48                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    49                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    50                                  ; 19/03/2015
    51                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    52                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    53                                  ; 24/03/2015
    54                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    55                                  ; 19/03/2015
    56                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    57                                  		     ; (at the end of the 1st 4MB)
    58                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    59                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    60                                  
    61                                  ; 01/01/2022 (Retro UNIX 386 v1.2)
    62                                  ;; 27/12/2013
    63                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    64                                  
    65                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    66                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    67                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    68                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    69                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    70                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    71                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    72                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    73                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    74                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    75                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    76                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    77                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    78                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    79                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    80                                  ;----------------------------------------
    81                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    82                                  ;-----------------------------------------------------------------------------
    83                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    84                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    85                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    86                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    87                                  
    88                                  ; Memory Allocation Table Address
    89                                  ; 05/11/2014
    90                                  ; 31/10/2014
    91                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    92                                  					; the 1st 1 MB memory space.
    93                                  					; (This address must be aligned
    94                                  					;  on 128 KB boundary, if it will be
    95                                  					;  changed later.)
    96                                  					; ((lower 17 bits of 32 bit M.A.T.
    97                                  					;   address must be ZERO)).
    98                                  					; ((((Reason: 32 bit allocation 
    99                                  					;     instructions, dword steps)))
   100                                  					; (((byte >> 12 --> page >> 5)))  
   101                                  ;04/11/2014	
   102                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   103                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   104                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   105                                  ;
   106                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   107                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   108                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   109                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   110                                  
   111                                  ; 17/02/2015 (unix386.s)
   112                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   113                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   114                                  ;
   115                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   116                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   117                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   118                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   119                                  
   120                                  
   121                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   122                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   123                                  ;
   124                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   125                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   126                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   127                                  		      ; otherwise it is standard FDPT with physical values 	
   128                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   129                                  		      ; (obsolete for IDE/ATA drives)
   130                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   131                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   132                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   133                                  			; Bit 4 : Reserved. Always 0
   134                                  			; Bit 3 : Set to 1 if more than 8 heads
   135                                  			; Bit 2-0 : Reserved. Alsways 0
   136                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   137                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   138                                  
   139                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   140                                  ; (11 bytes long) will be used by diskette handler/bios
   141                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   142                                  
   143                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   144                                  
   145                                  [ORG 0] 
   146                                  
   147                                  KSTART: ; 01/01/2022
   148                                  
   149                                  	; 12/11/2014
   150                                  	; Save boot drive number (that is default root drive)
   151 00000000 8816[4863]              	mov	[boot_drv], dl ; physical drv number
   152                                  
   153                                  	; Determine installed memory
   154                                  	; 31/10/2014
   155                                  	;
   156 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   157 00000007 CD15                    	int	15h	   ; for large configurations
   158 00000009 7308                    	jnc	short chk_ms
   159 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   160 0000000D CD15                    	int	15h
   161                                  	;	   
   162                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   163                                  	;out	70h, al ; select CMOS register
   164                                  	;in	al, 71h ; read data (1 byte)
   165                                  	;mov	cl, al
   166                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   167                                  	;out	70h, al ; select CMOS register
   168                                  	;in	al, 71h ; read data (1 byte)
   169                                  	;mov	ch, al
   170                                   	;      
   171 0000000F 89C1                    	mov	cx, ax
   172 00000011 31D2                    	xor	dx, dx
   173                                  chk_ms:
   174 00000013 890E[B465]              	mov	[mem_1m_1k], cx
   175 00000017 8916[B865]              	mov	[mem_16m_64k], dx
   176                                  	; 05/11/2014
   177                                  	;and	dx, dx
   178                                  	;jz	short L2
   179 0000001B 81F90004                        cmp     cx, 1024
   180 0000001F 7351                    	jnb	short L0
   181                                  		 ; insufficient memory_error	
   182                                  		 ; Minimum 2 MB memory is needed...
   183                                  oom_0: 
   184                                  	; 05/11/2014
   185                                  	; (real mode error printing)
   186 00000021 FB                      	sti
   187 00000022 BE[3600]                	mov	si, msg_out_of_memory
   188 00000025 BB0700                  	mov	bx, 7
   189 00000028 B40E                    	mov	ah, 0Eh	; write tty
   190                                  oom_1:
   191 0000002A AC                      	lodsb
   192 0000002B 08C0                    	or	al, al
   193 0000002D 7404                    	jz	short oom_2
   194 0000002F CD10                    	int	10h
   195 00000031 EBF7                    	jmp	short oom_1
   196                                  oom_2:
   197 00000033 F4                              hlt
   198 00000034 EBFD                    	jmp	short oom_2
   199                                  
   200                                  ; 28/11/2021 - Retro UNIX 386 v2 compatibility modification (on v1.1)
   201                                  ; 11/04/2021 - Retro UNIX 386 v2
   202                                  ; ((Real mode messages and buffers must be in the 1st 64K of the kernel))
   203                                  ; 20/02/2017 (TRDOS 386 v2)
   204                                  ; 05/11/2014
   205                                  msg_out_of_memory:
   206 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   207 00000039 496E73756666696369-             db      'Insufficient memory !'
   207 00000042 656E74206D656D6F72-
   207 0000004B 792021             
   208 0000004E 0D0A                    	db	0Dh, 0Ah
   209                                  _int13h_48h_buffer: ; 07/07/2016
   210 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   210 00000059 324D42206D656D6F72-
   210 00000062 79206973206E656564-
   210 0000006B 65642E29           
   211 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   212                                  
   213                                  L0:
   214                                  %include 'diskinit.s' ; 07/03/2015
   215                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
   216                              <1> ; (re-write kernel for test by using previous version without a major defect)
   217                              <1> ; ****************************************************************************
   218                              <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - DISKINIT.INC
   219                              <1> ; Last Modification: 12/07/2022
   220                              <1> 
   221                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   222                              <1> 
   223                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   224                              <1> 
   225                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.2)
   226                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   227                              <1> ;L0:
   228                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   229                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   230 00000072 BA7F00              <1> 	mov	dx, 7Fh
   231                              <1> L1:	
   232 00000075 FEC2                <1> 	inc	dl
   233 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   234                              <1> 			; Phoenix EDD v1.1 - EDD v3
   235 00000079 BBAA55              <1> 	mov	bx, 55AAh
   236 0000007C CD13                <1> 	int 	13h
   237 0000007E 721A                <1> 	jc	short L2
   238                              <1> 
   239 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   240 00000084 7514                <1> 	jne	short L2
   241 00000086 FE06[4B63]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   242 0000008A 8816[4A63]          <1>         mov     [last_drv], dl  ; last hard disk number
   243 0000008E BB[CE62]            <1> 	mov	bx, hd0_type - 80h
   244 00000091 01D3                <1> 	add	bx, dx	 
   245 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   246                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   247                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   248                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   249                              <1>                          ;            (EDD) ready (DPTE ready)
   250                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   251                              <1>                          ;            (EDD-3)
   252                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   253 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   254 00000098 72DB                <1> 	jb	short L1
   255                              <1> L2:
   256                              <1> 	; 23/11/2014
   257                              <1> 	; 19/11/2014
   258 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   259                              <1> 	; 04/02/2016 (esi -> si)
   260 0000009C BE[4C63]            <1> 	mov	si, fd0_type
   261                              <1> L3:
   262                              <1> 	; 14/01/2015
   263 0000009F 8816[4963]          <1> 	mov	[drv], dl
   264                              <1> 	;
   265 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   266 000000A5 CD13                <1> 	int	13h	
   267 000000A7 7210                <1> 	jc	short L4
   268                              <1> 		; BL = drive type (for floppy drives)
   269                              <1> 		; DL = number of floppy drives
   270                              <1> 		;		
   271                              <1> 		; ES:DI = Address of DPT from BIOS
   272                              <1> 		;
   273 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   274                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   275                              <1> 	; 14/01/2015
   276 000000AB E8BB01              <1> 	call	set_disk_parms
   277                              <1> 	; 10/12/2014
   278 000000AE 81FE[4C63]          <1> 	cmp	si, fd0_type
   279 000000B2 7705                <1> 	ja	short L4
   280 000000B4 46                  <1> 	inc	si ; fd1_type
   281 000000B5 B201                <1> 	mov	dl, 1
   282 000000B7 EBE6                <1> 	jmp	short L3
   283                              <1> L4:
   284                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   285 000000B9 B27F                <1> 	mov	dl, 7Fh
   286                              <1> 	; 24/12/2014 (Temporary)
   287 000000BB 803E[4B63]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   288                              <1> 	;ja	L10       ; yes, all fixed disk operations
   289                              <1> 			  ; will be performed according to
   290                              <1> 			  ; present EDD specification
   291                              <1> 	; 02/01/2022
   292 000000C0 7603                <1> 	jna	short L5
   293 000000C2 E99100              <1> 	jmp	L10
   294                              <1> L5:
   295 000000C5 FEC2                <1> 	inc 	dl
   296 000000C7 8816[4963]          <1>         mov     [drv], dl
   297 000000CB 8816[4A63]          <1>         mov     [last_drv], dl ; 14/01/2015
   298 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   299 000000D1 CD13                <1> 	int	13h	; (conventional function)
   300                              <1> 	;jc	L13	; fixed disk drive not ready
   301                              <1> 	; 02/01/2022
   302 000000D3 7303                <1> 	jnc	short L6
   303 000000D5 E98301              <1> 	jmp	L13
   304                              <1> L6:
   305 000000D8 8816[4B63]          <1>         mov     [hdc], dl ; number of drives
   306                              <1> 	;; 14/01/2013
   307                              <1> 	;;push	cx
   308 000000DC E88A01              <1> 	call	set_disk_parms
   309                              <1> 	;;pop	cx
   310                              <1> 	;
   311                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   312 000000DF 8A16[4963]          <1>         mov     dl, [drv]
   313 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   314 000000E6 80FA80              <1> 	cmp	dl, 80h
   315 000000E9 7603                <1> 	jna	short L7
   316 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   317                              <1> L7:	
   318 000000EE 31C0                <1> 	xor	ax, ax
   319 000000F0 8ED8                <1> 	mov	ds, ax
   320 000000F2 8B37                <1>         mov     si, [bx]
   321 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   322 000000F7 8ED8                <1> 	mov	ds, ax
   323 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   324                              <1> 	;jne	L12 ; invalid FDPT
   325                              <1> 	; 02/01/2022
   326 000000FC 7403                <1> 	je	short L7_8
   327 000000FE E95601              <1> 	jmp	L12
   328                              <1> L7_8:
   329 00000101 BF0000              <1> 	mov	di, HD0_DPT
   330 00000104 80FA80              <1> 	cmp	dl, 80h
   331 00000107 7603                <1> 	jna	short L8
   332 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   333                              <1> L8:
   334                              <1> 	; 30/12/2014
   335 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   336 0000010F 8EC0                <1> 	mov	es, ax
   337                              <1> 	; 24/12/2014
   338 00000111 B90800              <1> 	mov	cx, 8
   339 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   340 00000116 8CC8                <1> 	mov	ax, cs
   341 00000118 8ED8                <1> 	mov	ds, ax
   342                              <1> 	; 02/02/2015
   343 0000011A 8A0E[4963]          <1>         mov     cl, [drv]
   344 0000011E 88CB                <1> 	mov	bl, cl
   345 00000120 B8F001              <1> 	mov	ax, 1F0h
   346 00000123 80E301              <1> 	and	bl, 1
   347 00000126 7406                <1> 	jz	short L9
   348 00000128 C0E304              <1> 	shl	bl, 4
   349 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   350                              <1> L9:
   351 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   352 0000012F 050602              <1> 	add	ax, 206h
   353 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   354 00000133 88D8                <1> 	mov	al, bl
   355 00000135 04A0                <1> 	add	al, 0A0h
   356 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   357                              <1> 	;
   358 00000138 FE06[4963]          <1> 	inc	byte [drv]
   359 0000013C BB[CE62]            <1> 	mov	bx, hd0_type - 80h
   360 0000013F 01CB                <1> 	add	bx, cx
   361 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   362 00000144 A0[4B63]            <1> 	mov	al, [hdc]
   363 00000147 FEC8                <1> 	dec	al
   364                              <1> 	;jz	L13
   365                              <1> 	; 02/01/2022
   366 00000149 7408                <1> 	jz	short L9_10
   367 0000014B 80FA80              <1> 	cmp	dl, 80h
   368                              <1>         ;jna	L5
   369                              <1> 	;jmp	L13
   370                              <1> 	; 02/01/2022
   371 0000014E 7703                <1> 	ja	short L9_10
   372 00000150 E972FF              <1> 	jmp	L5
   373                              <1> L9_10:
   374 00000153 E90501              <1>         jmp     L13
   375                              <1> L10:
   376 00000156 FEC2                <1> 	inc 	dl
   377                              <1> 	; 25/12/2014
   378 00000158 8816[4963]          <1> 	mov	[drv], dl
   379 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   380 0000015E CD13                <1> 	int	13h	; (conventional function)
   381                              <1> 	;jc	L13
   382                              <1> 	; 02/01/2022
   383 00000160 72F1                <1> 	jc	short L9_10
   384                              <1> 	; 14/01/2015
   385 00000162 8A16[4963]          <1> 	mov	dl, [drv]
   386 00000166 52                  <1> 	push	dx
   387 00000167 51                  <1> 	push	cx
   388 00000168 E8FE00              <1> 	call	set_disk_parms
   389 0000016B 59                  <1> 	pop	cx
   390 0000016C 5A                  <1> 	pop	dx
   391                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.2
   392                              <1> 	; 04/02/2016 (esi -> si)
   393                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   394                              <1> 	;		 ; at the '_end' of kernel.
   395                              <1> 	;mov	word [si], 30
   396                              <1> 	; 06/07/2016
   397 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   398                              <1> 	; 09/07/2016
   399 00000170 B81E00              <1> 	mov	ax, 001Eh
   400 00000173 8824                <1> 	mov	[si], ah ; 0
   401 00000175 46                  <1> 	inc	si
   402 00000176 8904                <1> 	mov	word [si], ax
   403                              <1>  	; word [si] = 30
   404                              <1> 	;
   405 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   406 0000017A CD13                <1> 	int	13h
   407                              <1>         ;jc	L13
   408                              <1> 	; 02/01/2022
   409 0000017C 72D5                <1> 	jc	short L9_10
   410                              <1> 	; 04/02/2016 (ebx -> bx)
   411                              <1> 	; 14/01/2015
   412                              <1> 	;sub	bx, bx
   413 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   414 00000180 88D3                <1> 	mov	bl, dl
   415 00000182 80EB80              <1> 	sub	bl, 80h
   416 00000185 81C3[4E63]          <1> 	add	bx, hd0_type
   417 00000189 8A07                <1> 	mov 	al, [bx]
   418 0000018B 0C80                <1> 	or	al, 80h
   419 0000018D 8807                <1> 	mov 	[bx], al	
   420 0000018F 81EB[4C63]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   421 00000193 81C3[6E63]          <1> 	add	bx, drv.status
   422 00000197 8807                <1> 	mov	[bx], al
   423                              <1> 	; 04/02/2016 (eax -> ax)
   424 00000199 8B4410              <1> 	mov	ax, [si+16]
   425 0000019C 854412              <1> 	test	ax, [si+18]
   426 0000019F 7413                <1> 	jz	short L10_A0h 
   427                              <1> 			; 'CHS only' disks on EDD system 
   428                              <1> 			;  are reported with ZERO disk size
   429 000001A1 81EB[6E63]          <1> 	sub	bx, drv.status
   430 000001A5 C1E302              <1> 	shl	bx, 2
   431 000001A8 81C3[5263]          <1> 	add	bx, drv.size ; disk size (in sectors)
   432 000001AC 8907                <1> 	mov	[bx], ax
   433 000001AE 8B4412              <1> 	mov	ax, [si+18]
   434                              <1> 	;mov	[bx], ax
   435                              <1> 	; 02/01/2022 (BugFix)
   436 000001B1 894702              <1> 	mov	[bx+2], ax
   437                              <1> 
   438                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   439                              <1> 	 ; for CHS disks (28/02/2015)
   440                              <1> 	; 30/12/2014
   441 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   442 000001B7 88D0                <1> 	mov	al, dl
   443 000001B9 83E003              <1> 	and 	ax, 3
   444 000001BC C0E005              <1> 	shl	al, 5 ; *32
   445 000001BF 01C7                <1> 	add 	di, ax
   446 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   447 000001C4 8EC0                <1> 	mov	es, ax
   448                              <1> 	;
   449 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   450 000001C8 88CC                <1> 	mov	ah, cl	
   451 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   452 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   453 000001CE AB                  <1> 	stosw		
   454 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   455 000001D1 FEC0                <1> 	inc	al
   456 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   457 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   458 000001D6 AA                  <1> 	stosb
   459 000001D7 8A440C              <1> 	mov	al, [si+12]
   460 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   461 000001DB 31C0                <1>  	xor	ax, ax
   462                              <1> 	;dec	ax	 ; 02/01/2015 
   463 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   464                              <1> 	;xor	al, al	 ; 02/01/2015	
   465 000001DE AA                  <1> 	stosb		 ; reserved
   466 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   467                              <1> 		         ; (do not disable retries, 
   468                              <1> 			 ; more than 8 heads)
   469 000001E1 AA                  <1> 	stosb
   470 000001E2 8B4404              <1> 	mov	ax, [si+4]
   471 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   472                              <1> 	;push	ax	 ; 02/01/2015
   473 000001E6 8A4408              <1> 	mov	al, [si+8]
   474 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   475 000001EA 29C0                <1> 	sub 	ax, ax
   476                              <1> 	;pop	ax	 ; 02/01/2015	
   477 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   478 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   479 000001EF 243F                <1> 	and 	al, 3Fh	
   480 000001F1 AA                  <1> 	stosb
   481                              <1> 	;sub	al, al	 ; checksum
   482                              <1> 	;stosb
   483                              <1> 	;
   484 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   485 000001F5 AD                  <1> 	lodsw
   486 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   487 000001F7 AD                  <1> 	lodsw
   488 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   489                              <1> 	;
   490                              <1> 	; checksum calculation
   491 000001F9 89FE                <1> 	mov	si, di
   492 000001FB 06                  <1> 	push	es
   493 000001FC 1F                  <1> 	pop	ds
   494                              <1> 	;mov	cx, 16
   495 000001FD B90F00              <1> 	mov 	cx, 15
   496 00000200 29CE                <1> 	sub	si, cx
   497 00000202 30E4                <1> 	xor	ah, ah
   498                              <1> 	;del	cl
   499                              <1> L11:		
   500 00000204 AC                  <1> 	lodsb
   501 00000205 00C4                <1> 	add	ah, al
   502 00000207 E2FB                <1> 	loop	L11
   503                              <1> 	;
   504 00000209 88E0                <1> 	mov	al, ah
   505 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   506 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   507                              <1> 	;
   508 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   509 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   510                              <1> 	;
   511                              <1> 	; 23/02/2015
   512 00000210 57                  <1> 	push	di
   513                              <1> 	; ES:DI points to DPTE (FDPTE) location
   514                              <1> 	;mov	cx, 8
   515 00000211 B108                <1> 	mov	cl, 8
   516 00000213 F3A5                <1> 	rep	movsw	
   517                              <1> 	;
   518                              <1> 	; 23/02/2015
   519                              <1> 	; (P)ATA drive and LBA validation
   520                              <1> 	; (invalidating SATA drives and setting
   521                              <1> 	; CHS type I/O for old type fixed disks)
   522 00000215 5B                  <1> 	pop	bx
   523 00000216 8CC8                <1> 	mov	ax, cs
   524 00000218 8ED8                <1> 	mov	ds, ax
   525 0000021A 268B07              <1> 	mov	ax, [es:bx]
   526 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   527 00000220 7418                <1> 	je	short L11a
   528 00000222 3D7001              <1> 	cmp	ax, 170h
   529 00000225 7413                <1> 	je	short L11a
   530                              <1> 	; invalidation 
   531                              <1> 	; (because base port address is not 1F0h or 170h)
   532 00000227 30FF                <1> 	xor	bh, bh
   533 00000229 88D3                <1> 	mov	bl, dl
   534 0000022B 80EB80              <1> 	sub	bl, 80h
   535 0000022E C687[4E63]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   536 00000233 808F[7063]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   537 00000238 EB14                <1> 	jmp	short L11b
   538                              <1> L11a:	
   539                              <1> 	; LBA validation
   540 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   541 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   542 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   543                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   544 00000242 28FF                <1> 	sub	bh, bh
   545 00000244 88D3                <1> 	mov	bl, dl
   546 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   547 00000249 80A7[7063]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   548                              <1> 				; bit 0 = LBA ready bit
   549                              <1> 	; 'diskio' procedure will check this bit !
   550                              <1> L11b:
   551 0000024E 3A16[4A63]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   552 00000252 7307                <1>         jnb     short L13
   553 00000254 E9FFFE              <1>         jmp     L10
   554                              <1> L12:
   555                              <1> 	; Restore data registers
   556 00000257 8CC8                <1> 	mov	ax, cs
   557 00000259 8ED8                <1> 	mov	ds, ax	
   558                              <1> L13:
   559                              <1> 	; 13/12/2014
   560 0000025B 0E                  <1> 	push	cs
   561 0000025C 07                  <1> 	pop	es
   562                              <1> L14:
   563 0000025D B411                <1> 	mov 	ah, 11h
   564 0000025F CD16                <1> 	int 	16h
   565                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   566                              <1> 	; 02/01/2022
   567 00000261 7447                <1> 	jz	short L16
   568 00000263 B010                <1> 	mov	al, 10h
   569 00000265 CD16                <1> 	int 	16h
   570 00000267 EBF4                <1> 	jmp 	short L14
   571                              <1> L15:
   572                              <1> 
   573                              <1> ; //////
   574                              <1> 
   575                              <1> ; 02/01/2022 - Retro UNIX 386 v1.2
   576                              <1> %if 0
   577                              <1> 	; 24/11/2014
   578                              <1> 	; 19/11/2014
   579                              <1> 	; 14/11/2014
   580                              <1> 	; Temporary code for disk searching code check
   581                              <1> 	;
   582                              <1> 	; This code will show existing (usable) drives and also
   583                              <1> 	; will show EDD interface support status for hard disks		
   584                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   585                              <1> 	; no need to get it again in protected mode...) 
   586                              <1> 	;	
   587                              <1> 	; 13/11/2014
   588                              <1> 	mov	bx, 7
   589                              <1> 	mov	ah, 0Eh
   590                              <1> 	mov	al, [fd0_type]
   591                              <1> 	and	al, al
   592                              <1> 	jz	short L15a
   593                              <1> 	mov	dl, al
   594                              <1> 	mov	al, 'F'
   595                              <1> 	int 	10h
   596                              <1> 	mov	al, 'D'
   597                              <1> 	int 	10h
   598                              <1> 	mov	al, '0'
   599                              <1> 	int 	10h
   600                              <1> 	mov	al, ' '
   601                              <1> 	int	10h
   602                              <1> 	call	L15c
   603                              <1> 	mov	al, ' '
   604                              <1> 	int	10h
   605                              <1> 	;
   606                              <1> 	mov	al, [fd1_type]
   607                              <1> 	and	al, al
   608                              <1> 	jz	short L15a
   609                              <1> 	mov	dl, al
   610                              <1> 	mov	al, 'F'
   611                              <1> 	int 	10h
   612                              <1> 	mov	al, 'D'
   613                              <1> 	int 	10h
   614                              <1> 	mov	al, '1'
   615                              <1> 	int 	10h
   616                              <1> 	mov	al, ' '
   617                              <1> 	int	10h
   618                              <1> 	call	L15c
   619                              <1> 	mov	al, ' '
   620                              <1> 	int	10h
   621                              <1> 	mov	al, ' '
   622                              <1> 	int	10h
   623                              <1> L15a:
   624                              <1> 	mov	al, [hd0_type]
   625                              <1> 	and	al, al
   626                              <1> 	jz	short L15b
   627                              <1> 	mov	dl, al
   628                              <1> 	mov	al, 'H'
   629                              <1> 	int 	10h
   630                              <1> 	mov	al, 'D'
   631                              <1> 	int 	10h
   632                              <1> 	mov	al, '0'
   633                              <1> 	int 	10h
   634                              <1> 	mov	al, ' '
   635                              <1> 	int 	10h
   636                              <1> 	call	L15c
   637                              <1> 	mov	al, ' '
   638                              <1> 	int	10h
   639                              <1> 	;
   640                              <1> 	mov	al, [hd1_type]
   641                              <1> 	and	al, al
   642                              <1> 	jz	short L15b
   643                              <1> 	mov	dl, al
   644                              <1> 	mov	al, 'H'
   645                              <1> 	int 	10h
   646                              <1> 	mov	al, 'D'
   647                              <1> 	int 	10h
   648                              <1> 	mov	al, '1'
   649                              <1> 	int 	10h
   650                              <1> 	mov	al, ' '
   651                              <1> 	int 	10h
   652                              <1> 	call	L15c
   653                              <1> 	mov	al, ' '
   654                              <1> 	int	10h
   655                              <1> 	;
   656                              <1> 	mov	al, [hd2_type]
   657                              <1> 	and	al, al
   658                              <1> 	jz	short L15b
   659                              <1> 	mov	dl, al
   660                              <1> 	mov	al, 'H'
   661                              <1> 	int 	10h
   662                              <1> 	mov	al, 'D'
   663                              <1> 	int 	10h
   664                              <1> 	mov	al, '2'
   665                              <1> 	int 	10h
   666                              <1> 	mov	al, ' '
   667                              <1> 	int 	10h
   668                              <1> 	call	L15c
   669                              <1> 	mov	al, ' '
   670                              <1> 	int	10h
   671                              <1> 	;
   672                              <1> 	mov	al, [hd3_type]
   673                              <1> 	and	al, al
   674                              <1> 	jz	short L15b
   675                              <1> 	mov	dl, al
   676                              <1> 	mov	al, 'H'
   677                              <1> 	int 	10h
   678                              <1> 	mov	al, 'D'
   679                              <1> 	int 	10h
   680                              <1> 	mov	al, '3'
   681                              <1> 	int 	10h
   682                              <1> 	mov	al, ' '
   683                              <1> 	int 	10h
   684                              <1> 	call	L15c
   685                              <1> 	mov	al, ' '
   686                              <1> 	int	10h
   687                              <1> 	;
   688                              <1> L15b:
   689                              <1> 	mov	al, 0Dh
   690                              <1> 	int 	10h	
   691                              <1> 	mov	al, 0Ah
   692                              <1> 	int 	10h
   693                              <1> 	;;xor	ah, ah
   694                              <1> 	;;int 	16h	
   695                              <1> 	;
   696                              <1>         ;jmp	L16  ; jmp short L16
   697                              <1>         ; 02/01/2022
   698                              <1> 	jmp	short L16
   699                              <1> 	;
   700                              <1> L15c:
   701                              <1> 	mov	dh, dl
   702                              <1> 	shr	dh, 4
   703                              <1> 	add	dh, 30h
   704                              <1> 	and	dl, 15
   705                              <1> 	add	dl, 30h
   706                              <1> 	mov	al, dh
   707                              <1> 	int	10h
   708                              <1> 	mov	al, dl
   709                              <1> 	int	10h
   710                              <1> 	retn
   711                              <1> 	;
   712                              <1> 	; end of temporary code for disk searching code check
   713                              <1> 
   714                              <1> %endif
   715                              <1> 
   716                              <1> ; //////
   717                              <1> 
   718                              <1> set_disk_parms:
   719                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
   720                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
   721                              <1> 	; 09/05/2022
   722                              <1> 	;	disksize = cylinders*spt*heads (*)
   723                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   724                              <1> 	;
   725                              <1> 	; 04/02/2016 (ebx -> bx)
   726                              <1> 	; 10/07/2015
   727                              <1> 	; 14/01/2015
   728                              <1> 	;push	bx
   729 00000269 28FF                <1> 	sub	bh, bh
   730 0000026B 8A1E[4963]          <1> 	mov	bl, [drv]
   731 0000026F 80FB80              <1> 	cmp	bl, 80h
   732 00000272 7203                <1> 	jb	short sdp0
   733 00000274 80EB7E              <1> 	sub	bl, 7Eh
   734                              <1> sdp0:	
   735 00000277 81C3[6E63]          <1> 	add	bx, drv.status
   736 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   737                              <1> 	;
   738 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   739 00000280 88CC                <1> 	mov	ah, cl ; 
   740 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   741 00000285 81EB[6E63]          <1> 	sub	bx, drv.status
   742 00000289 D0E3                <1> 	shl	bl, 1
   743                              <1> 	; 12/07/2022
   744                              <1> 	;add	bx, drv.cylinders
   745 0000028B 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count
   746                              <1> 	;mov	[bx], ax
   747 0000028C 50                  <1> 	push	ax ; ** cylinders
   748                              <1> 	;sub	bx, drv.cylinders
   749                              <1> 	;add	bx, drv.heads
   750 0000028D 30E4                <1> 	xor	ah, ah
   751 0000028F 88F0                <1> 	mov	al, dh ; heads
   752 00000291 40                  <1> 	inc	ax
   753                              <1> 	;mov	[bx], ax
   754                              <1>         ;sub	bx, drv.heads
   755                              <1>         ;add	bx, drv.spt
   756 00000292 30ED                <1> 	xor	ch, ch
   757 00000294 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   758                              <1> 	;mov	[bx], cx
   759                              <1>         ;sub	bx, drv.spt
   760 00000297 D1E3                <1> 	shl	bx, 1
   761 00000299 81C3[5263]          <1> 	add	bx, drv.size ; disk size (in sectors)
   762                              <1> 	; LBA size = cylinders * heads * secpertrack
   763 0000029D F7E1                <1> 	mul	cx 
   764 0000029F 89C2                <1> 	mov	dx, ax	; heads*spt
   765 000002A1 58                  <1> 	pop	ax ; ** cylinders
   766                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   767                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   768 000002A2 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)
   769 000002A4 8907                <1> 	mov	[bx], ax
   770 000002A6 895702              <1> 	mov	[bx+2], dx
   771                              <1> 	;
   772                              <1> 	;pop	bx
   773 000002A9 C3                  <1> 	retn
   774                              <1> 
   775                              <1> ;align 2
   776                              <1> 
   777                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   778                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   779                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   780                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   781                              <1> 
   782                              <1> ;last_drv:
   783                              <1> ;	db  0
   784                              <1> ;drv_status:
   785                              <1> ;	db  0,0,0,0,0,0
   786                              <1> ;	db 0
   787                              <1> 
   788                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   789                              <1> 
   790                              <1> L16:
   215                                  _L0:	
   216                                  	; 10/11/2014
   217 000002AA FA                           	cli	; Disable interrupts (clear interrupt flag)
   218                                  		; Reset Interrupt MASK Registers (Master&Slave)
   219                                  	;mov	al, 0FFh	; mask off all interrupts
   220                                  	;out	21h, al		; on master PIC (8259)
   221                                  	;jmp 	$+2  ; (delay)
   222                                  	;out	0A1h, al	; on slave PIC (8259)
   223                                  	;
   224                                  	; Disable NMI 
   225 000002AB B080                    	mov   	al, 80h 
   226 000002AD E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   227                                  	; 23/02/2015
   228 000002AF 90                      	nop			;
   229                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   230                                  				; for preventing unknown state (!?)
   231                                  
   232                                  	; 01/01/2022 (Retro UNIX 386 v1.2)
   233                                  	%define KERNELFSIZE KEND-KSTART 
   234                                  	;
   235                                   	; 20/08/2014
   236                                  	; Moving the kernel 64 KB back (to physical address 0)
   237                                  	; DS = CS = 1000h
   238                                  	; 05/11/2014
   239 000002B0 31C0                    	xor	ax, ax
   240 000002B2 8EC0                    	mov	es, ax ; ES = 0
   241                                  	;
   242                                  	;;mov	cx, (KEND - KLOAD)/4
   243                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 01/01/2022
   244 000002B4 B9DE32                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   245 000002B7 31F6                    	xor	si, si
   246 000002B9 31FF                    	xor	di, di
   247                                  	;rep	movsd
   248 000002BB F3A5                    	rep	movsw ; 02/01/2022
   249                                  	;
   250 000002BD 06                      	push	es ; 0
   251 000002BE 68[C202]                	push	L17
   252 000002C1 CB                      	retf
   253                                  	;
   254                                  L17:
   255                                  	; Turn off the floppy drive motor
   256 000002C2 BAF203                          mov     dx, 3F2h
   257 000002C5 EE                              out     dx, al ; 0 ; 31/12/2013
   258                                  
   259                                  	; Enable access to memory above one megabyte
   260                                  L18:
   261 000002C6 E464                    	in	al, 64h
   262 000002C8 A802                    	test	al, 2
   263 000002CA 75FA                            jnz     short L18
   264 000002CC B0D1                    	mov	al, 0D1h	; Write output port
   265 000002CE E664                    	out	64h, al
   266                                  L19:
   267 000002D0 E464                    	in	al, 64h
   268 000002D2 A802                    	test	al, 2
   269 000002D4 75FA                            jnz     short L19
   270 000002D6 B0DF                    	mov	al, 0DFh	; Enable A20 line
   271 000002D8 E660                    	out	60h, al
   272                                  ;L20:
   273                                  	;
   274                                  	; Load global descriptor table register
   275                                  
   276                                          ;mov	ax, cs
   277                                          ;mov	ds, ax
   278                                  
   279 000002DA 2E0F0116[7060]                  lgdt    [cs:gdtd]
   280                                  
   281 000002E0 0F20C0                          mov     eax, cr0
   282                                  	;or 	eax, 1
   283 000002E3 40                      	inc     ax
   284 000002E4 0F22C0                  	mov     cr0, eax
   285                                  
   286                                  	; Jump to 32 bit code
   287                                  	
   288 000002E7 66                      	db	66h 		; Prefix for 32-bit
   289 000002E8 EA                      	db	0EAh 		; Opcode for far jump
   290 000002E9 [EF020000]              	dd	StartPM 	; Offset to start, 32-bit
   291                                  				; (1000h:StartPM = StartPM + 10000h)
   292 000002ED 0800                    	dw	KCODE		; This is the selector for CODE32_DESCRIPTOR,
   293                                  				; assuming that StartPM resides in code32
   294                                  
   295                                  [BITS 32] 
   296                                  
   297                                  StartPM:
   298                                  	; Kernel Base Address = 0 ; 30/12/2013
   299 000002EF 66B81000                	mov	ax, KDATA	; Save data segment identifier
   300 000002F3 8ED8                            mov	ds, ax		; Move a valid data segment into DS register
   301 000002F5 8EC0                           	mov	es, ax		; Move data segment into ES register
   302 000002F7 8EE0                           	mov	fs, ax		; Move data segment into FS register
   303 000002F9 8EE8                          	mov	gs, ax		; Move data segment into GS register
   304 000002FB 8ED0                            mov	ss, ax		; Move data segment into SS register
   305 000002FD BC00000900                      mov	esp, 90000h	; Move the stack pointer to 090000h
   306                                  
   307                                  clear_bss: ; Clear uninitialized data area
   308                                  	; 11/03/2015
   309 00000302 31C0                    	xor	eax, eax ; 0
   310                                  	;mov	ecx, (bss_end - bss_start)/4
   311                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   312                                  	; 12/12/2021
   313 00000304 B9B90C0000              	mov	ecx, BSS_SIZE/4
   314 00000309 BF[C0650000]            	mov	edi, bss_start	
   315 0000030E F3AB                    	rep	stosd  		
   316                                  
   317                                  memory_init:
   318                                  	; Initialize memory allocation table and page tables
   319                                  	;
   320                                  	; 02/01/2022 (Retro UNIX 386 v1.2)
   321                                  	; 16/11/2014
   322                                  	; 15/11/2014
   323                                  	; 07/11/2014
   324                                  	; 06/11/2014
   325                                  	; 05/11/2014
   326                                  	; 04/11/2014
   327                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   328                                  	;
   329                                  ;	xor	eax, eax
   330                                  ;	xor 	ecx, ecx
   331 00000310 B108                    	mov	cl, 8
   332 00000312 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   333 00000317 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   334                                  				   ; for the first 1 MB memory
   335                                  	;
   336 00000319 8B0D[B4650000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   337                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   338                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   339                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   340 0000031F C1E902                  	shr	ecx, 2	; 02/01/2022
   341 00000322 890D[30680000]          	mov	[free_pages], ecx
   342 00000328 8B15[B8650000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   343                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   344                                  				   ; between 16 MB and 4 GB.
   345                                  	;or	dx, dx
   346 0000032E 09D2                    	or	edx, edx ; 02/01/2022
   347 00000330 7412                    	jz	short mi_0
   348                                  	;
   349                                  	;mov	ax, dx
   350 00000332 89D0                    	mov	eax, edx ; 02/01/2022
   351 00000334 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   352 00000337 0105[30680000]          	add	[free_pages], eax
   353 0000033D 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   354 00000342 EB06                    	jmp	short mi_1
   355                                  mi_0:
   356                                  	;mov	ax, cx
   357 00000344 89C8                    	mov	eax, ecx ; 02/01/2022	 
   358 00000346 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   359                                  mi_1:
   360 0000034A A3[2C680000]            	mov	[memory_size], eax ; Total available memory in pages
   361                                  				   ; 1 alloc. tbl. bit = 1 memory page
   362                                  				   ; 32 allocation bits = 32 mem. pages
   363                                  	;
   364 0000034F 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   365 00000354 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   366                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   367                                  				   ;  --> x M.A.T. pages, if y = 0
   368                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   369 00000357 A3[40680000]            	mov	[mat_size], eax ; 02/01/2022
   370 0000035C C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   371                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   372 0000035F 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   373                                  	; Set/Calculate Kernel's Page Directory Address
   374 00000361 81C300001000            	add	ebx, MEM_ALLOC_TBL
   375 00000367 891D[28680000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   376                                  				   ; just after the last M.A.T. page
   377                                  	;
   378 0000036D 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   379 00000370 A3[38680000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   380                                  	;			   ; (allocation status search must be
   381                                  				   ; stopped after here)
   382 00000375 31C0                    	xor	eax, eax
   383 00000377 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   384                                  	;push	cx
   385 00000378 51                      	push	ecx ; 02/01/2022 
   386 00000379 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   387                                  				   ; count of 32 allocation bits
   388 0000037C F3AB                    	rep	stosd
   389                                  	;pop	cx
   390 0000037E 59                      	pop	ecx ; 02/01/2022
   391 0000037F 40                      	inc	eax		   ; 0
   392 00000380 80E11F                  	and	cl, 31		   ; remain bits
   393 00000383 7412                    	jz	short mi_4
   394 00000385 8907                    	mov	[edi], eax	   ; reset
   395                                  mi_2:
   396 00000387 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   397 0000038A FEC9                    	dec	cl
   398 0000038C 7404                    	jz	short mi_3
   399 0000038E FEC0                    	inc	al
   400 00000390 EBF5                    	jmp	short mi_2
   401                                  mi_3:
   402 00000392 28C0                    	sub	al, al	   	   ; 0
   403 00000394 83C704                  	add	edi, 4		   ; 15/11/2014
   404                                  mi_4:
   405 00000397 09D2                    	or	edx, edx ; 02/01/2022
   406                                  	;or	dx, dx		  ; check 16M to 4G memory space
   407 00000399 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   408                                  	;	
   409 0000039B B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   410                                  	;	
   411 000003A0 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   412 000003A2 7405                    	jz	short mi_5	  ; jump if EDI points to 
   413                                  				  ;         end of first 16 MB	
   414                                  	;shr	ecx, 1		  ; convert to dword count
   415                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   416 000003A4 C1E902                  	shr	ecx, 2	; 02/01/2022
   417 000003A7 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   418                                  				  ; (memory hole under 16 MB)
   419                                  mi_5:
   420 000003A9 89D1                    	mov	ecx, edx ; 02/01/2022
   421                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   422 000003AB D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   423 000003AD 9C                      	pushf			  ; 16/11/2014		
   424 000003AE 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   425 000003AF F3AB                    	rep	stosd
   426 000003B1 40                      	inc	eax		  ; 0
   427 000003B2 9D                      	popf			  ; 16/11/2014
   428 000003B3 7305                    	jnc	short mi_6
   429 000003B5 6648                    	dec	ax		  ; eax = 0000FFFFh
   430 000003B7 AB                      	stosd
   431 000003B8 6640                    	inc	ax		  ; 0		
   432                                  mi_6:
   433 000003BA 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   434 000003BC 7309                    	jnb	short mi_7	  ; end of memory allocation table
   435                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   436 000003BE 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   437 000003C0 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   438                                  	;shr	ecx, 1		  ; to dword count
   439                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   440 000003C2 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   441 000003C5 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   442                                  mi_7:
   443                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   444 000003C7 BA00001000              	mov	edx, MEM_ALLOC_TBL
   445                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   446                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   447 000003CC 8B0D[40680000]          	mov	ecx, [mat_size] ; 02/01/2022
   448                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   449 000003D2 89D7                    	mov	edi, edx
   450 000003D4 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   451                                  				  ; byte offset in M.A.T.
   452                                  				  ; (1 M.A.T. byte points to 
   453                                  				  ;	      32768 bytes)
   454                                  				  ; Note: MEM_ALLOC_TBL address 
   455                                  				  ; must be aligned on 128 KB 
   456                                  				  ; boundary!
   457 000003D7 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   458                                  	; eax = 0
   459 000003D9 290D[30680000]          	sub	[free_pages], ecx ; 07/11/2014
   460                                  mi_8:
   461 000003DF 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   462                                  	;dec	bl
   463 000003E2 FEC9                    	dec	cl
   464 000003E4 7404                    	jz	short mi_9
   465 000003E6 FEC0                    	inc	al
   466 000003E8 EBF5                    	jmp	short mi_8
   467                                  mi_9:
   468                                  	;
   469                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   470                                  	;		(allocate pages for system page tables)
   471                                  
   472                                  	; edx = MEM_ALLOC_TBL
   473 000003EA 8B0D[2C680000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   474 000003F0 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   475 000003F6 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   476                                  				 ; page table count (PDE count)
   477                                  	;
   478 000003F9 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   479                                  	;
   480 000003FA 41                      	inc	ecx		 ; +1 for kernel page directory	
   481                                  	;
   482 000003FB 290D[30680000]          	sub	[free_pages], ecx ; 07/11/2014
   483                                  	;
   484 00000401 8B35[28680000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   485 00000407 C1EE0C                  	shr	esi, 12		 ; convert to page number
   486                                  mi_10:
   487 0000040A 89F0                    	mov	eax, esi	 ; allocation bit offset
   488 0000040C 89C3                    	mov	ebx, eax
   489 0000040E C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   490 00000411 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   491                                  				 ;   to align on dword boundary
   492 00000414 83E01F                  	and	eax, 31		 ; set allocation bit position 
   493                                  				 ;  (bit 0 to bit 31)
   494                                  	;
   495 00000417 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   496                                  	;
   497 00000419 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   498                                  	;
   499 0000041C 46                      	inc	esi		 ; next page table
   500 0000041D E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   501                                  				 ; (ecx = page table count + 1)
   502                                  	;
   503 0000041F 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   504                                  	;
   505                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   506                                  	;
   507                                  	; Initialize Kernel's Page Directory
   508 00000420 8B3D[28680000]          	mov	edi, [k_page_dir]
   509 00000426 89F8                    	mov	eax, edi
   510 00000428 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   511                                  		     	      ; supervisor + read&write + present
   512 0000042A 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   513                                  mi_11:
   514 0000042C 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   515                                  			        ; EAX points to next page table
   516 00000431 AB                      	stosd
   517 00000432 E2F8                    	loop	mi_11
   518 00000434 29C0                    	sub	eax, eax	; Empty PDE
   519                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   520                                  	; 02/01/2022
   521 00000436 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   522 00000438 29D1                    	sub	ecx, edx
   523 0000043A 7402                    	jz	short mi_12
   524 0000043C F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   525                                  	;
   526                                  	; Initialization of Kernel's Page Directory is OK, here.
   527                                  mi_12:
   528                                  	; Initialize Kernel's Page Tables
   529                                  	;
   530                                  	; (EDI points to address of page table 0)
   531                                  	; eax = 0
   532 0000043E 8B0D[2C680000]          	mov	ecx, [memory_size] ; memory size in pages
   533 00000444 89CA                    	mov	edx, ecx	; (***)
   534 00000446 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   535                                  			     ; supervisor + read&write + present
   536                                  mi_13:
   537 00000448 AB                      	stosd
   538 00000449 0500100000              	add	eax, 4096	
   539 0000044E E2F8                    	loop	mi_13
   540                                  	; 02/01/2022
   541 00000450 66B9FF03                	mov	cx, 1023
   542 00000454 21CA                    	and	edx, ecx
   543                                  	;and	dx, 1023	; (***)
   544 00000456 7407                    	jz	short mi_14
   545                                  	;mov	cx, 1024	
   546                                  	; 02/01/2022
   547                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   548 00000458 41                      	inc	ecx ; ecx = 1024
   549 00000459 29D1                    	sub	ecx, edx
   550                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   551 0000045B 31C0                    	xor	eax, eax
   552 0000045D F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   553                                  				; of the last page table
   554                                  mi_14:
   555                                  	;  Initialization of Kernel's Page Tables is OK, here.
   556                                  	;
   557 0000045F 89F8                    	mov	eax, edi	; end of the last page table page
   558                                  			        ; (beginging of user space pages)
   559 00000461 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   560 00000464 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   561                                  				; aligning on dword boundary
   562                                  	 
   563 00000466 A3[3C680000]            	mov	[first_page], eax
   564 0000046B A3[34680000]            	mov	[next_page], eax ; The first free page pointer
   565                                  				 ; for user programs
   566                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   567                                  	;
   568                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   569                                  	;
   570                                  	
   571                                  	; Enable paging
   572                                  	;
   573 00000470 A1[28680000]                    mov     eax, [k_page_dir]
   574 00000475 0F22D8                  	mov	cr3, eax
   575 00000478 0F20C0                  	mov	eax, cr0
   576 0000047B 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   577 00000480 0F22C0                  	mov	cr0, eax
   578                                          ;jmp    KCODE:StartPMP
   579                                  
   580 00000483 EA                      	db 0EAh 		; Opcode for far jump
   581 00000484 [8A040000]                      dd StartPMP		; 32 bit offset
   582 00000488 0800                    	dw KCODE		; kernel code segment descriptor
   583                                  
   584                                  StartPMP:
   585                                  	; 06/11//2014
   586                                  	; Clear video page 0
   587                                  	;
   588                                  	; Temporary Code
   589                                  	;
   590                                  	;mov	ecx, 80*25/2
   591 0000048A 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   592 0000048E BF00800B00              	mov	edi, 0B8000h
   593 00000493 57                      	push	edi ; * ; 02/01/2022
   594 00000494 31C0                    	xor	eax, eax	; black background, black fore color
   595 00000496 F3AB                    	rep	stosd
   596                                  	
   597                                  	; 19/08/2014
   598                                  	; Kernel Base Address = 0
   599                                  	; It is mapped to (physically) 0 in the page table.
   600                                  	; So, here is exactly 'StartPMP' address.
   601                                  	;
   602                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   603                                  	;;mov	esi, msgPM
   604                                  	;; 14/08/2015 (kernel version message will appear
   605                                  	;;	       when protected mode and paging is enabled)
   606 00000498 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   607 0000049A BE[84630000]            	mov	esi, msgKVER
   608 0000049F 5F                      	pop	edi ; * ; 02/01/2022
   609                                  	;mov	edi, 0B8000h ; 27/08/2014
   610                                  	; 20/08/2014
   611 000004A0 E890010000              	call	printk
   612                                  
   613                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   614                                  	; // Set IRQ offsets
   615                                  	;
   616                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   617                                  	;
   618                                  					;; ICW1
   619 000004A5 B011                    	mov	al, 11h			; Initialization sequence
   620 000004A7 E620                    	out	20h, al			; 	8259A-1
   621                                  	; jmp 	$+2
   622 000004A9 E6A0                    	out	0A0h, al		; 	8259A-2
   623                                  					;; ICW2
   624 000004AB B020                    	mov	al, 20h			; Start of hardware ints (20h)
   625 000004AD E621                    	out	21h, al			;	for 8259A-1
   626                                  	; jmp 	$+2
   627 000004AF B028                    	mov	al, 28h			; Start of hardware ints (28h)
   628 000004B1 E6A1                    	out	0A1h, al		; 	for 8259A-2
   629                                  					;
   630 000004B3 B004                    	mov	al, 04h			;; ICW3
   631 000004B5 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   632                                  	; jmp 	$+2
   633 000004B7 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   634 000004B9 E6A1                    	out	0A1h, al		;
   635                                  					;; ICW4
   636 000004BB B001                    	mov	al, 01h	 		;
   637 000004BD E621                    	out	21h, al			; 	8086 mode, normal EOI	
   638                                  	; jmp 	$+2
   639 000004BF E6A1                    	out	0A1h, al		;	for both chips.
   640                                  
   641                                  	;mov	al, 0FFh	; mask off all interrupts for now
   642                                  	;out	21h, al
   643                                  	;; jmp 	$+2
   644                                  	;out	0A1h, al
   645                                  
   646                                  	; 02/04/2015
   647                                  	; 26/03/2015 System call (INT 30h) modification
   648                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   649                                  	;
   650                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   651                                  	;  setup_idt:
   652                                  	;
   653                                          ;; 16/02/2015
   654                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   655                                  	; 21/08/2014 (timer_int)
   656 000004C1 BE[7C600000]            	mov	esi, ilist
   657 000004C6 8D3D[C0650000]          	lea	edi, [idt]
   658                                  	; 26/03/2015
   659                                  	;mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   660                                  	; 02/01/2022
   661 000004CC B130                    	mov	cl, 48 ; ecx = 48
   662                                  	; 02/04/2015
   663 000004CE BB00000800              	mov	ebx, 80000h
   664                                  rp_sidt1:
   665 000004D3 AD                      	lodsd
   666 000004D4 89C2                    	mov	edx, eax
   667 000004D6 66BA008E                	mov	dx, 8E00h
   668 000004DA 6689C3                  	mov	bx, ax
   669 000004DD 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   670                                         			        ; /* interrupt gate - dpl=0, present */
   671 000004DF AB                      	stosd	; selector & offset bits 0-15 	
   672 000004E0 89D0                    	mov	eax, edx
   673 000004E2 AB                      	stosd	; attributes & offset bits 16-23
   674 000004E3 E2EE                    	loop	rp_sidt1
   675 000004E5 B110                    	mov	cl, 16		; 16 software interrupts (INT 30h to INT 3Fh)
   676                                  rp_sidt2:
   677 000004E7 AD                      	lodsd
   678 000004E8 21C0                    	and	eax, eax
   679 000004EA 7413                    	jz	short rp_sidt3
   680 000004EC 89C2                    	mov	edx, eax
   681 000004EE 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   682 000004F2 6689C3                  	mov	bx, ax
   683 000004F5 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   684 000004F7 AB                      	stosd
   685 000004F8 89D0                    	mov	eax, edx
   686 000004FA AB                      	stosd
   687 000004FB E2EA                    	loop	rp_sidt2
   688 000004FD EB16                    	jmp	short sidt_OK
   689                                  rp_sidt3:
   690 000004FF B8[59090000]            	mov	eax, ignore_int
   691 00000504 89C2                    	mov	edx, eax
   692 00000506 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   693 0000050A 6689C3                  	mov	bx, ax
   694 0000050D 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   695                                  rp_sidt4:
   696 0000050F AB                      	stosd
   697 00000510 92                      	xchg	eax, edx
   698 00000511 AB                      	stosd
   699 00000512 92                      	xchg	edx, eax
   700 00000513 E2FA                    	loop	rp_sidt4
   701                                  sidt_OK: 
   702 00000515 0F011D[76600000]        	lidt 	[idtd]
   703                                  	;
   704                                  	; TSS descriptor setup ; 24/03/2015
   705 0000051C B8[C0670000]            	mov	eax, task_state_segment
   706 00000521 66A3[6A600000]          	mov	[gdt_tss0], ax
   707 00000527 C1C010                  	rol	eax, 16
   708 0000052A A2[6C600000]            	mov	[gdt_tss1], al
   709 0000052F 8825[6F600000]          	mov	[gdt_tss2], ah
   710 00000535 66C705[26680000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   710 0000053D 00                 
   711                                  		; 
   712                                  		; IO Map Base address (When this address points
   713                                  		; to end of the TSS, CPU does not use IO port 
   714                                  		; permission bit map for RING 3 IO permissions, 
   715                                  		; access to any IO ports in ring 3 will be forbidden.)
   716                                   		;
   717                                  	;mov	[tss.esp0], esp ; TSS offset 4
   718                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   719 0000053E 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   720                                  			 ; occurs (or a system call -software INT- is requested)
   721                                  			 ; while cpu running in ring 3 (in user mode).				
   722                                  			 ; (Kernel stack pointer and segment will be loaded
   723                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   724 00000542 0F00D8                  	ltr	ax  ; Load task register
   725                                  	;
   726                                  esp0_set0:
   727                                  	; 30/07/2015
   728 00000545 8B0D[2C680000]          	mov 	ecx, [memory_size] ; memory size in pages
   729 0000054B C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   730 0000054E 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   731                                  			  ; (kernel mode virtual address)
   732 00000554 7605                    	jna	short esp0_set1
   733                                  	;
   734                                  	; If available memory > CORE (end of the 1st 4 MB)
   735                                  	; set stack pointer to CORE
   736                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   737                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   738 00000556 B900004000              	mov	ecx, CORE
   739                                  esp0_set1:
   740 0000055B 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   741                                  esp0_set_ok:
   742                                  	; 30/07/2015 (**tss.esp0**) 
   743 0000055D 8925[C4670000]          	mov	[tss.esp0], esp
   744 00000563 66C705[C8670000]10-             mov     word [tss.ss0], KDATA
   744 0000056B 00                 
   745                                  	; 14/08/2015
   746                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   747                                  	;
   748                                  	;cli	; Disable interrupts (for CPU)
   749                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   750                                  	;
   751 0000056C 30C0                    	xor	al, al		; Enable all hardware interrupts!
   752 0000056E E621                    	out	21h, al		; (IBM PC-AT compatibility)
   753 00000570 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   754 00000572 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   755                                  				; (Even if related hardware component
   756                                  				;  does not exist!)
   757                                  	; Enable NMI 
   758 00000574 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   759 00000576 E670                    	out  	70h, al
   760                                  	; 23/02/2015
   761 00000578 90                      	nop
   762 00000579 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   763                                  				; for preventing unknown state (!?)
   764                                  	;
   765                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   766                                  	;
   767                                  	; 02/09/2014
   768 0000057B 6631DB                  	xor	bx, bx
   769 0000057E 66BA0002                	mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   770 00000582 E8240F0000              	call	set_cpos
   771                                  	;
   772                                  	; 06/11/2014
   773                                  	; Temporary Code
   774                                  	;
   775 00000587 E899100000              	call	memory_info
   776                                  	; 14/08/2015
   777                                  	;call	getch ; 28/02/2015
   778                                  drv_init:
   779 0000058C FB                      	sti	; Enable Interrupts 
   780                                  	; 06/02/2015
   781 0000058D 8B15[4E630000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   782 00000593 668B1D[4C630000]        	mov	bx, [fd0_type] ; fd0, fd1
   783                                  	; 22/02/2015
   784 0000059A 6621DB                  	and	bx, bx
   785 0000059D 751B                    	jnz	short di1
   786                                  	;
   787 0000059F 09D2                    	or 	edx, edx
   788 000005A1 7529                    	jnz	short di2
   789                                  	;
   790                                  setup_error:
   791 000005A3 BE[6D640000]            	mov 	esi, setup_error_msg
   792                                  psem:	
   793 000005A8 AC                      	lodsb
   794 000005A9 08C0                    	or	al, al
   795                                  	;jz	short haltx ; 22/02/2015
   796 000005AB 7426                    	jz	short di3
   797 000005AD 56                      	push	esi
   798 000005AE 31DB                    	xor	ebx, ebx ; 0
   799                                  			; Video page 0 (bl=0)
   800 000005B0 B407                    	mov	ah, 07h ; Black background, 
   801                                  			; light gray forecolor
   802 000005B2 E8EA0D0000              	call	write_tty
   803 000005B7 5E                      	pop	esi
   804 000005B8 EBEE                    	jmp	short psem
   805                                  
   806                                  di1:
   807                                  	; supress 'jmp short T6'
   808                                  	;  (activate fdc motor control code)
   809 000005BA 66C705[B6060000]90-     	mov	word [T5], 9090h ; nop
   809 000005C2 90                 
   810                                  	;
   811                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   812                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   813                                  	;stosw
   814                                  	;mov 	ax, cs
   815                                  	;stosw
   816                                  	;; 16/02/2015
   817                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   818                                  	;
   819 000005C3 E81A1A0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   820                                  	;
   821 000005C8 09D2                    	or	edx, edx
   822 000005CA 7407                            jz      short di3
   823                                  di2:
   824 000005CC E8431A0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   825 000005D1 72D0                            jc      short setup_error
   826                                  di3:
   827 000005D3 E821100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   828                                  	;
   829 000005D8 E8BB590000              	call	display_disks ; 07/03/2015  (Temporary)
   830                                  ;haltx:
   831                                  	; 14/08/2015
   832                                  	;call	getch ; 22/02/2015
   833 000005DD FB                      	sti	; Enable interrupts (for CPU)
   834                                  	; 14/08/2015
   835                                  	;mov 	ecx, 0FFFFFFFh
   836                                  	; 22/11/2021
   837 000005DE B9FFFF2F00              	mov 	ecx, 02FFFFFh
   838                                  md_info_msg_wait:
   839 000005E3 51                      	push 	ecx
   840 000005E4 B001                    	mov	al, 1
   841 000005E6 8A25[56680000]          	mov 	ah, [ptty] ; active (current) video page
   842 000005EC E87C560000              	call	getc_n
   843 000005F1 59                      	pop	ecx
   844 000005F2 7502                    	jnz	short md_info_msg_ok
   845 000005F4 E2ED                    	loop	md_info_msg_wait
   846                                  md_info_msg_ok:
   847                                  	; 30/06/2015
   848 000005F6 E8E2230000              	call	sys_init
   849                                  	;
   850                                  	;jmp 	cpu_reset ; 22/02/2015
   851                                  hang:
   852                                  	; 04/12/2021
   853 000005FB 29C0                    	sub	eax, eax
   854                                  _hang:	
   855                                  	; 23/02/2015
   856                                  	;sti			; Enable interrupts
   857 000005FD F4                      	hlt
   858                                  	;
   859                                  	;nop
   860                                  	;; 03/12/2014
   861                                  	;; 28/08/2014
   862                                  	;mov	ah, 11h
   863                                  	;call	getc
   864                                  	;jz     _c8
   865                                  	;
   866                                  	; 23/02/2015
   867                                  	; 06/02/2015
   868                                  	; 07/09/2014
   869 000005FE 31DB                    	xor	ebx, ebx
   870 00000600 8A1D[56680000]          	mov	bl, [ptty]	; active_page
   871 00000606 89DE                    	mov	esi, ebx
   872 00000608 66D1E6                  	shl 	si, 1
   873 0000060B 81C6[58680000]          	add	esi, ttychr
   874 00000611 668B06                  	mov	ax, [esi]
   875                                  	;and	ax, ax
   876                                  	;;jz	short _c8
   877                                  	;jz	short hang
   878                                  	; 04/12/2021
   879 00000614 21C0                    	and	eax, eax
   880 00000616 74E5                    	jz	short _hang
   881 00000618 66C7060000              	mov	word [esi], 0
   882 0000061D 80FB03                  	cmp	bl, 3		; Video page 3
   883                                  	;jb	short _c8
   884 00000620 72D9                    	jb	short hang
   885                                  	;	
   886                                  	; 02/09/2014
   887 00000622 B40E                    	mov	ah, 0Eh		; Yellow character 
   888                                  				; on black background
   889                                  	; 30/11/2021 (32 bit reg push-pop)
   890                                  	; 07/09/2014
   891                                  nxtl:
   892 00000624 53                      	push	ebx
   893                                  	;
   894                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   895                                  				; bh = 0 (video mode)
   896                                  				; Retro UNIX 386 v1 - Video Mode 0
   897                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   898 00000625 50                      	push	eax
   899 00000626 E8760D0000              	call 	write_tty
   900 0000062B 58                      	pop	eax
   901                                  	;pop	bx
   902 0000062C 5B                      	pop	ebx
   903 0000062D 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   904                                  	;jne	short _c8
   905 0000062F 75CA                    	jne	short hang
   906 00000631 B00A                    	mov	al, 0Ah		; next line
   907 00000633 EBEF                    	jmp	short nxtl
   908                                  	
   909                                  ;_c8:
   910                                  ;	; 25/08/2014
   911                                  ;	cli			; Disable interrupts
   912                                  ;	mov	al, [scounter + 1]
   913                                  ;	and	al, al
   914                                  ;	jnz	hang
   915                                  ;	call	rtc_p
   916                                  ;	jmp     hang
   917                                  
   918                                  
   919                                  	; 27/08/2014
   920                                  	; 20/08/2014
   921                                  printk:
   922                                          ;mov    edi, [scr_row]
   923                                  pkl:
   924 00000635 AC                      	lodsb
   925 00000636 08C0                    	or 	al, al
   926 00000638 7404                    	jz	short pkr
   927 0000063A 66AB                    	stosw
   928 0000063C EBF7                    	jmp	short pkl
   929                                  pkr:
   930 0000063E C3                      	retn
   931                                  
   932                                  ; 25/07/2015
   933                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   934                                  ; 17/02/2015
   935                                  ; 06/02/2015 (unix386.s)
   936                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   937                                  ;
   938                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   939                                  ;
   940                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   941                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   942                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   943                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   944                                  ;									       :
   945                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   946                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   947                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   948                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   949                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   950                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   951                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   952                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   953                                  ;-------------------------------------------------------------------------------
   954                                  ;
   955                                  
   956                                  timer_int:	; IRQ 0
   957                                  ;int_08h:	; Timer
   958                                  	; 14/10/2015
   959                                  	; Here, we are simulating system call entry (for task switch)
   960                                  	; (If multitasking is enabled, 
   961                                  	; 'clock' procedure may jump to 'sysrelease')
   962 0000063F 1E                      	push	ds
   963 00000640 06                      	push	es
   964 00000641 0FA0                    	push	fs
   965 00000643 0FA8                    	push	gs
   966 00000645 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   967 00000646 66B91000                	mov     cx, KDATA
   968 0000064A 8ED9                            mov     ds, cx
   969 0000064C 8EC1                            mov     es, cx
   970 0000064E 8EE1                            mov     fs, cx
   971 00000650 8EE9                            mov     gs, cx
   972                                  	;
   973 00000652 0F20D9                  	mov	ecx, cr3
   974 00000655 890D[F8060000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   975                                  	;
   976 0000065B 3B0D[28680000]          	cmp 	ecx, [k_page_dir]
   977 00000661 741F                    	je	short T3
   978                                  	;
   979                                  	; timer interrupt has been occurred while OS is in user mode
   980 00000663 A3[646D0000]            	mov 	[u.r0], eax
   981 00000668 89E1                    	mov	ecx, esp
   982 0000066A 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   983 0000066D 890D[5C6D0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   984 00000673 8925[606D0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   985                                  	;
   986 00000679 8B0D[28680000]          	mov	ecx, [k_page_dir]
   987 0000067F 0F22D9                  	mov	cr3, ecx
   988                                  T3:
   989 00000682 FB                      	sti				; INTERRUPTS BACK ON
   990 00000683 66FF05[A4680000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   991 0000068A 7507                    	JNZ	short T4		; GO TO TEST_DAY
   992 0000068C 66FF05[A6680000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   993                                  T4:					; TEST_DAY
   994 00000693 66833D[A6680000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   995 0000069B 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   996 0000069D 66813D[A4680000]B0-     	CMP	word [TIMER_LOW],0B0H
   996 000006A5 00                 
   997 000006A6 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   998                                  
   999                                  ;-----	TIMER HAS GONE 24 HOURS
  1000                                  	;;SUB	AX,AX
  1001                                  	;MOV	[TIMER_HIGH],AX
  1002                                  	;MOV	[TIMER_LOW],AX
  1003 000006A8 29C0                    	sub	eax, eax
  1004 000006AA A3[A4680000]            	mov	[TIMER_LH], eax
  1005                                  	;	
  1006 000006AF C605[A8680000]01        	MOV	byte [TIMER_OFL],1
  1007                                  
  1008                                  ;-----	TEST FOR DISKETTE TIME OUT
  1009                                  
  1010                                  T5:
  1011                                  	; 23/12/2014
  1012 000006B6 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1013                                  					; (9090h) if a floppy disk
  1014                                  					; is detected.
  1015                                  	;mov	al,[CS:MOTOR_COUNT]
  1016 000006B8 A0[AB680000]            	mov	al, [MOTOR_COUNT]
  1017 000006BD FEC8                    	dec	al
  1018                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1019 000006BF A2[AB680000]            	mov	[MOTOR_COUNT], al
  1020                                  	;mov	[ORG_MOTOR_COUNT], al
  1021 000006C4 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1022 000006C6 B0F0                    	mov 	al,0F0h
  1023                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1024 000006C8 2005[AA680000]          	and	[MOTOR_STATUS], al
  1025                                  	;and	[ORG_MOTOR_STATUS], al
  1026 000006CE B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1027                                  					; bit 2 = enable controller
  1028                                  					;	1 = normal operation
  1029                                  					;	0 = reset	
  1030                                  					; bit 0, 1 = drive select
  1031                                  					; bit 4-7 = motor running bits 
  1032 000006D0 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1033 000006D4 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1034                                  T6:	
  1035                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1036                                  					; TIMER TICK INTERRUPT
  1037                                  	;;inc	word [wait_count] ;;27/02/2015
  1038                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1039                                  	;;;;cli
  1040                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1041 000006D5 FF15[F0060000]          	call	[x_timer] ; 14/05/2015
  1042                                  T7:
  1043                                  	; 14/10/2015
  1044 000006DB B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1045 000006DD FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1046 000006DE E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1047                                  	;
  1048 000006E0 A1[F8060000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1049 000006E5 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1050                                  	;
  1051 000006E8 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1052                                  	;
  1053 000006E9 0FA9                    	pop	gs
  1054 000006EB 0FA1                    	pop	fs
  1055 000006ED 07                      	pop	es
  1056 000006EE 1F                      	pop	ds
  1057 000006EF CF                      	iretd	; return from interrupt
  1058                                  
  1059                                  
  1060                                  ; ////////////////
  1061                                  
  1062                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1063                                  x_timer:
  1064 000006F0 [FC060000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1065                                  	;dd	clock
  1066                                  
  1067                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1068                                  x_rtci:
  1069 000006F4 [320A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1070                                  
  1071                                  ; 14/10/2015
  1072 000006F8 00000000                cr3reg: dd 0
  1073                                  
  1074                                  	; 04/12/2021 - Retro UNIX 386 v1.2
  1075                                  	; 06/02/2015
  1076                                  	; 07/09/2014
  1077                                  	; 21/08/2014
  1078                                  u_timer:
  1079                                  ;timer_int:	; IRQ 0
  1080                                  	; 06/02/2015
  1081                                  	;push	eax
  1082                                  	;push	edx
  1083                                  	;push	ecx
  1084                                  	;push	ebx
  1085                                  	;push	ds
  1086                                  	;push	es
  1087                                  	;mov	eax, KDATA
  1088                                  	;mov	ds, ax
  1089                                  	;mov	es, ax
  1090 000006FC FF05[6C680000]          	inc	dword [tcount]
  1091 00000702 BB[F6630000]            	mov	ebx, tcountstr + 4
  1092                                  	;mov	ax, [tcount]
  1093                                  	; 04/12/2021
  1094 00000707 A1[6C680000]            	mov	eax, [tcount]
  1095 0000070C B90A000000              	mov	ecx, 10
  1096                                  rp_divtcnt:
  1097 00000711 31D2                    	xor	edx, edx
  1098 00000713 F7F1                    	div	ecx
  1099 00000715 80C230                  	add	dl, 30h
  1100 00000718 8813                    	mov	[ebx], dl
  1101                                  	;or	ax, ax
  1102                                  	; 04/12/2021
  1103 0000071A 09C0                    	or	eax, eax
  1104 0000071C 7403                    	jz	short print_lzero
  1105 0000071E 4B                      	dec	ebx
  1106 0000071F EBF0                    	jmp	short rp_divtcnt
  1107                                  print_lzero:
  1108 00000721 81FB[F2630000]          	cmp	ebx, tcountstr
  1109 00000727 7606                    	jna	short print_tcount
  1110 00000729 4B                      	dec	ebx
  1111 0000072A C60330                   	mov	byte [ebx], 30h
  1112 0000072D EBF2                    	jmp	short print_lzero
  1113                                  print_tcount:
  1114 0000072F 56                      	push	esi
  1115 00000730 57                      	push	edi
  1116 00000731 BE[CE630000]            	mov	esi, timer_msg ; Timer interrupt message
  1117                                  	; 07/09/2014
  1118                                  	;mov	bx, 1	; Video page 1
  1119                                  	; 04/12/2021
  1120 00000736 29DB                    	sub	ebx, ebx
  1121                                  	;inc	bl ; ebx = 1
  1122                                  	; 02/01/2022
  1123 00000738 B306                    	mov	bl, 6	; Video page 6
  1124                                  ptmsg:
  1125 0000073A AC                      	lodsb
  1126 0000073B 08C0                    	or	al, al
  1127 0000073D 740D                    	jz	short ptmsg_ok
  1128 0000073F 56                      	push	esi
  1129                                  	;push	bx
  1130                                  	; 04/12/2021
  1131 00000740 53                              push	ebx
  1132 00000741 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1133 00000743 E8590C0000              	call 	write_tty
  1134                                  	;pop	bx
  1135                                  	; 04/12/2021
  1136 00000748 5B                      	pop	ebx
  1137 00000749 5E                      	pop	esi
  1138 0000074A EBEE                    	jmp	short ptmsg
  1139                                  	;; 27/08/2014
  1140                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1141                                  	;call	printk
  1142                                  	;
  1143                                  ptmsg_ok:
  1144                                  	; 07/09/2014
  1145                                  	;xor	dx, dx		; column 0, row 0
  1146                                  	; 04/12/2021
  1147 0000074C 31D2                    	xor	edx, edx
  1148 0000074E E8580D0000              	call	set_cpos	; set cursor position to 0,0 
  1149                                  	; 23/02/2015
  1150                                  	; 25/08/2014
  1151                                  	;mov	ebx, scounter		; (seconds counter)
  1152                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1153                                  ;	dec	byte [scounter+1]
  1154                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1155                                  ;	jns	short u_timer_retn
  1156                                  	; 26/02/2015
  1157                                  ;	call	rtc_p
  1158                                  ;	mov	ebx, scounter		; (seconds counter)
  1159                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1160                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1161                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1162                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1163                                  ;	mov	byte [ebx], 5
  1164                                  ;	inc	byte [ebx+1] ; 19
  1165                                  ;;timer_eoi:
  1166                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1167                                  ;;	out	20h, al	; 8259 PORT
  1168                                  	;
  1169                                  ;u_timer_retn:  ; 06/02/2015
  1170 00000753 5F                      	pop	edi
  1171 00000754 5E                      	pop	esi
  1172                                  	;pop	es
  1173                                  	;pop	ds
  1174                                  	;pop	ebx
  1175                                  	;pop	ecx
  1176                                  	;pop	edx
  1177                                  	;pop	eax
  1178                                  	;iret
  1179 00000755 C3                      	retn	; 06/02/2015
  1180                                  
  1181                                  	; 28/08/2014
  1182                                  irq0:
  1183 00000756 6A00                            push 	dword 0
  1184 00000758 EB48                    	jmp	short which_irq
  1185                                  irq1:
  1186 0000075A 6A01                            push 	dword 1
  1187 0000075C EB44                    	jmp	short which_irq
  1188                                  irq2:
  1189 0000075E 6A02                            push 	dword 2
  1190 00000760 EB40                    	jmp	short which_irq
  1191                                  irq3:
  1192                                  	; 20/11/2015
  1193                                  	; 24/10/2015
  1194 00000762 2EFF15[64310000]        	call	dword [cs:com2_irq3]
  1195 00000769 6A03                    	push 	dword 3
  1196 0000076B EB35                    	jmp	short which_irq
  1197                                  irq4:
  1198                                  	; 20/11/2015
  1199                                  	; 24/10/2015
  1200 0000076D 2EFF15[60310000]        	call	dword [cs:com1_irq4]
  1201 00000774 6A04                            push 	dword 4
  1202 00000776 EB2A                    	jmp	short which_irq
  1203                                  irq5:
  1204 00000778 6A05                            push 	dword 5
  1205 0000077A EB26                    	jmp	short which_irq
  1206                                  irq6:
  1207 0000077C 6A06                            push 	dword 6
  1208 0000077E EB22                    	jmp	short which_irq
  1209                                  irq7:
  1210 00000780 6A07                            push 	dword 7
  1211 00000782 EB1E                    	jmp	short which_irq
  1212                                  irq8:
  1213 00000784 6A08                            push 	dword 8
  1214 00000786 EB1A                    	jmp	short which_irq
  1215                                  irq9:
  1216 00000788 6A09                            push 	dword 9
  1217 0000078A EB16                    	jmp	short which_irq
  1218                                  irq10:
  1219 0000078C 6A0A                            push 	dword 10
  1220 0000078E EB12                    	jmp	short which_irq
  1221                                  irq11:
  1222 00000790 6A0B                            push 	dword 11
  1223 00000792 EB0E                    	jmp	short which_irq
  1224                                  irq12:
  1225 00000794 6A0C                            push 	dword 12
  1226 00000796 EB0A                    	jmp	short which_irq
  1227                                  irq13:
  1228 00000798 6A0D                            push 	dword 13
  1229 0000079A EB06                    	jmp	short which_irq
  1230                                  irq14:
  1231 0000079C 6A0E                            push 	dword 14
  1232 0000079E EB02                    	jmp	short which_irq
  1233                                  irq15:
  1234 000007A0 6A0F                            push 	dword 15
  1235                                  	;jmp	short which_irq
  1236                                  
  1237                                  	; 19/10/2015
  1238                                  	; 29/08/2014
  1239                                  	; 21/08/2014
  1240                                  which_irq:
  1241 000007A2 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1242 000007A5 53                      	push	ebx
  1243 000007A6 56                      	push	esi
  1244 000007A7 57                      	push	edi
  1245 000007A8 1E                      	push 	ds
  1246 000007A9 06                      	push 	es
  1247                                  	;
  1248 000007AA 88C3                    	mov	bl, al
  1249                                  	;
  1250 000007AC B810000000              	mov	eax, KDATA
  1251 000007B1 8ED8                    	mov	ds, ax
  1252 000007B3 8EC0                    	mov	es, ax
  1253                                  	; 19/10/2015
  1254 000007B5 FC                      	cld
  1255                                          ; 27/08/2014
  1256 000007B6 8105[7C630000]A000-             add     dword [scr_row], 0A0h
  1256 000007BE 0000               
  1257                                  	;
  1258 000007C0 B417                    	mov	ah, 17h	; blue (1) background, 
  1259                                  			; light gray (7) forecolor
  1260 000007C2 8B3D[7C630000]                  mov     edi, [scr_row]
  1261 000007C8 B049                    	mov	al, 'I'
  1262 000007CA 66AB                    	stosw
  1263 000007CC B052                    	mov	al, 'R'
  1264 000007CE 66AB                    	stosw
  1265 000007D0 B051                    	mov	al, 'Q'
  1266 000007D2 66AB                    	stosw
  1267 000007D4 B020                    	mov	al, ' '
  1268 000007D6 66AB                    	stosw
  1269 000007D8 88D8                    	mov	al, bl
  1270 000007DA 3C0A                    	cmp	al, 10
  1271 000007DC 7208                    	jb	short iix
  1272 000007DE B031                    	mov	al, '1'
  1273 000007E0 66AB                    	stosw
  1274 000007E2 88D8                    	mov	al, bl
  1275 000007E4 2C0A                    	sub	al, 10
  1276                                  iix:
  1277 000007E6 0430                    	add	al, '0'
  1278 000007E8 66AB                    	stosw
  1279 000007EA B020                    	mov	al, ' '
  1280 000007EC 66AB                    	stosw
  1281 000007EE B021                    	mov	al, '!'
  1282 000007F0 66AB                    	stosw
  1283 000007F2 B020                    	mov	al, ' '
  1284 000007F4 66AB                    	stosw
  1285                                  	; 23/02/2015
  1286 000007F6 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1287                                  	;jna	iiret
  1288                                  	; 04/12/2021
  1289 000007F9 7604                    	jna	short iiz
  1290                                  iiy:
  1291 000007FB B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1292 000007FD E6A0                    	out	0A0h, al ; the 2nd 8259
  1293                                  iiz:
  1294 000007FF E983010000              	jmp     iiret
  1295                                  	;
  1296                                  	; 22/08/2014
  1297                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1298                                  	;out	20h, al	; 8259 PORT
  1299                                  	;
  1300                                  	;pop	es
  1301                                  	;pop	ds
  1302                                  	;pop	edi
  1303                                  	;pop	esi
  1304                                  	;pop	ebx
  1305                                  	;pop 	eax
  1306                                  	;iret
  1307                                  
  1308                                  	; 02/04/2015
  1309                                  	; 25/08/2014
  1310                                  exc0:
  1311 00000804 6A00                            push 	dword 0
  1312 00000806 E990000000                      jmp     cpu_except
  1313                                  exc1:
  1314 0000080B 6A01                            push 	dword 1
  1315 0000080D E989000000                      jmp     cpu_except
  1316                                  exc2:
  1317 00000812 6A02                            push 	dword 2
  1318 00000814 E982000000                      jmp     cpu_except
  1319                                  exc3:
  1320 00000819 6A03                            push 	dword 3
  1321 0000081B EB7E                            jmp     cpu_except
  1322                                  exc4:
  1323 0000081D 6A04                            push 	dword 4
  1324 0000081F EB7A                            jmp     cpu_except
  1325                                  exc5:
  1326 00000821 6A05                            push 	dword 5
  1327 00000823 EB76                            jmp     cpu_except
  1328                                  exc6:
  1329 00000825 6A06                            push 	dword 6
  1330 00000827 EB72                            jmp     cpu_except
  1331                                  exc7:
  1332 00000829 6A07                            push 	dword 7
  1333 0000082B EB6E                            jmp     cpu_except
  1334                                  exc8:
  1335                                  	; [esp] = Error code
  1336 0000082D 6A08                            push 	dword 8
  1337 0000082F EB5C                            jmp     cpu_except_en
  1338                                  exc9:
  1339 00000831 6A09                            push 	dword 9
  1340 00000833 EB66                            jmp     cpu_except
  1341                                  exc10:
  1342                                  	; [esp] = Error code
  1343 00000835 6A0A                            push 	dword 10
  1344 00000837 EB54                            jmp     cpu_except_en
  1345                                  exc11:
  1346                                  	; [esp] = Error code
  1347 00000839 6A0B                            push 	dword 11
  1348 0000083B EB50                            jmp     cpu_except_en
  1349                                  exc12:
  1350                                  	; [esp] = Error code
  1351 0000083D 6A0C                            push 	dword 12
  1352 0000083F EB4C                            jmp     cpu_except_en
  1353                                  exc13:
  1354                                  	; [esp] = Error code
  1355 00000841 6A0D                            push 	dword 13
  1356 00000843 EB48                            jmp     cpu_except_en
  1357                                  exc14:
  1358                                  	; [esp] = Error code
  1359 00000845 6A0E                            push 	dword 14
  1360 00000847 EB44                    	jmp	short cpu_except_en
  1361                                  exc15:
  1362 00000849 6A0F                            push 	dword 15
  1363 0000084B EB4E                            jmp     cpu_except
  1364                                  exc16:
  1365 0000084D 6A10                            push 	dword 16
  1366 0000084F EB4A                            jmp     cpu_except
  1367                                  exc17:
  1368                                  	; [esp] = Error code
  1369 00000851 6A11                            push 	dword 17
  1370 00000853 EB38                    	jmp	short cpu_except_en
  1371                                  exc18:
  1372 00000855 6A12                            push 	dword 18
  1373 00000857 EB42                    	jmp	short cpu_except
  1374                                  exc19:
  1375 00000859 6A13                            push 	dword 19
  1376 0000085B EB3E                    	jmp	short cpu_except
  1377                                  exc20:
  1378 0000085D 6A14                            push 	dword 20
  1379 0000085F EB3A                    	jmp	short cpu_except
  1380                                  exc21:
  1381 00000861 6A15                            push 	dword 21
  1382 00000863 EB36                    	jmp	short cpu_except
  1383                                  exc22:
  1384 00000865 6A16                            push 	dword 22
  1385 00000867 EB32                    	jmp	short cpu_except
  1386                                  exc23:
  1387 00000869 6A17                            push 	dword 23
  1388 0000086B EB2E                    	jmp	short cpu_except
  1389                                  exc24:
  1390 0000086D 6A18                            push 	dword 24
  1391 0000086F EB2A                    	jmp	short cpu_except
  1392                                  exc25:
  1393 00000871 6A19                            push 	dword 25
  1394 00000873 EB26                    	jmp	short cpu_except
  1395                                  exc26:
  1396 00000875 6A1A                            push 	dword 26
  1397 00000877 EB22                    	jmp	short cpu_except
  1398                                  exc27:
  1399 00000879 6A1B                            push 	dword 27
  1400 0000087B EB1E                    	jmp	short cpu_except
  1401                                  exc28:
  1402 0000087D 6A1C                            push 	dword 28
  1403 0000087F EB1A                    	jmp	short cpu_except
  1404                                  exc29:
  1405 00000881 6A1D                            push 	dword 29
  1406 00000883 EB16                    	jmp	short cpu_except
  1407                                  exc30:
  1408 00000885 6A1E                            push 	dword 30
  1409 00000887 EB04                    	jmp	short cpu_except_en
  1410                                  exc31:
  1411 00000889 6A1F                            push 	dword 31
  1412 0000088B EB0E                            jmp     short cpu_except
  1413                                  
  1414                                  	; 02/01/2022 (Retro UNIX 386 v1.2)
  1415                                  	; 19/10/2015
  1416                                  	; 19/09/2015
  1417                                  	; 01/09/2015
  1418                                  	; 28/08/2015
  1419                                  	; 28/08/2014
  1420                                  cpu_except_en:
  1421 0000088D 87442404                	xchg	eax, [esp+4] ; Error code
  1422 00000891 36A3[D4680000]          	mov	[ss:error_code], eax
  1423 00000897 58                      	pop	eax  ; Exception number
  1424 00000898 870424                  	xchg	eax, [esp]
  1425                                  		; eax = eax before exception
  1426                                  		; [esp] -> exception number
  1427                                  		; [esp+4] -> EIP to return
  1428                                  	; 19/10/2015
  1429                                  	; 19/09/2015
  1430                                  	; 01/09/2015
  1431                                  	; 28/08/2015
  1432                                  	; 29/08/2014
  1433                                  	; 28/08/2014
  1434                                  	; 25/08/2014
  1435                                  	; 21/08/2014
  1436                                  cpu_except:	; CPU Exceptions
  1437 0000089B FC                      	cld
  1438 0000089C 870424                  	xchg	eax, [esp] 
  1439                                  		; eax = Exception number
  1440                                  		; [esp] = eax (before exception)
  1441 0000089F 53                      	push	ebx
  1442 000008A0 56                      	push	esi
  1443 000008A1 57                      	push	edi
  1444 000008A2 1E                      	push 	ds
  1445 000008A3 06                      	push 	es
  1446                                  	; 28/08/2015
  1447 000008A4 66BB1000                	mov	bx, KDATA
  1448 000008A8 8EDB                    	mov	ds, bx
  1449 000008AA 8EC3                    	mov	es, bx
  1450 000008AC 0F20DB                  	mov	ebx, cr3
  1451 000008AF 53                      	push	ebx ; (*) page directory
  1452                                  	; 19/10/2015
  1453 000008B0 FC                      	cld
  1454                                  	; 25/03/2015
  1455 000008B1 8B1D[28680000]          	mov	ebx, [k_page_dir]
  1456 000008B7 0F22DB                  	mov	cr3, ebx
  1457                                  	; 28/08/2015
  1458 000008BA 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1459 000008BD 7513                    	jne	short cpu_except_nfp
  1460 000008BF E8D31E0000              	call	page_fault_handler
  1461 000008C4 21C0                    	and 	eax, eax
  1462                                  	;jz	iiretp ; 01/09/2015
  1463                                  	; 02/01/2022
  1464 000008C6 7505                    	jnz	short cpu_except_pf
  1465 000008C8 E9B6000000              	jmp	iiretp
  1466                                  cpu_except_pf:
  1467 000008CD B80E000000              	mov	eax, 0Eh ; 14
  1468                                  cpu_except_nfp:
  1469                                  	; 02/04/2015
  1470 000008D2 BB[FB050000]            	mov	ebx, hang
  1471 000008D7 875C241C                	xchg	ebx, [esp+28]
  1472                                  		; EIP (points to instruction which faults)
  1473                                  	  	; New EIP (hang)
  1474 000008DB 891D[D8680000]          	mov	[FaultOffset], ebx
  1475 000008E1 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1476 000008E9 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1477                                  	;
  1478 000008F1 88C4                    	mov	ah, al
  1479 000008F3 240F                    	and	al, 0Fh
  1480 000008F5 3C09                    	cmp	al, 9
  1481 000008F7 7602                    	jna	short h1ok
  1482 000008F9 0407                    	add	al, 'A'-':'
  1483                                  h1ok:
  1484 000008FB D0EC                    	shr	ah, 1
  1485 000008FD D0EC                    	shr	ah, 1
  1486 000008FF D0EC                    	shr	ah, 1
  1487 00000901 D0EC                    	shr	ah, 1
  1488 00000903 80FC09                  	cmp	ah, 9
  1489 00000906 7603                    	jna	short h2ok
  1490 00000908 80C407                  	add	ah, 'A'-':'
  1491                                  h2ok:	
  1492 0000090B 86E0                    	xchg 	ah, al	
  1493 0000090D 66053030                	add	ax, '00'
  1494 00000911 66A3[0A640000]          	mov	[excnstr], ax
  1495                                  	;
  1496                                  	; 29/08/2014
  1497 00000917 A1[D8680000]            	mov	eax, [FaultOffset]
  1498 0000091C 51                      	push	ecx
  1499 0000091D 52                      	push	edx
  1500 0000091E 89E3                    	mov	ebx, esp
  1501                                  	; 28/08/2015
  1502 00000920 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1503                                  			  ; to hexadecimal string
  1504                                  	;mov	ecx, 10	    ; divisor to convert
  1505                                  			    ; binary number to decimal string
  1506                                  b2d1:
  1507 00000925 31D2                    	xor	edx, edx
  1508 00000927 F7F1                    	div	ecx
  1509                                  	;push	dx
  1510                                  	; 02/01/2022
  1511 00000929 52                      	push	edx
  1512 0000092A 39C8                    	cmp	eax, ecx
  1513 0000092C 73F7                    	jnb	short b2d1
  1514 0000092E BF[15640000]            	mov	edi, EIPstr ; EIP value
  1515                                  			    ; points to instruction which faults
  1516                                  	; 28/08/2015
  1517 00000933 89C2                    	mov	edx, eax
  1518                                  b2d2:
  1519                                  	;add	al, '0'
  1520 00000935 8A82[DD160000]          	mov	al, [edx+hexchrs]
  1521 0000093B AA                      	stosb		    ; write hexadecimal digit to its place
  1522 0000093C 39E3                    	cmp	ebx, esp
  1523 0000093E 7605                    	jna	short b2d3
  1524                                  	; 02/01/2022
  1525 00000940 58                      	pop	eax
  1526                                  	;pop	ax
  1527 00000941 88C2                    	mov	dl, al
  1528 00000943 EBF0                    	jmp	short b2d2
  1529                                  b2d3:
  1530 00000945 B068                    	mov 	al, 'h' ; 28/08/2015
  1531 00000947 AA                      	stosb
  1532 00000948 B020                    	mov	al, 20h	    ; space
  1533 0000094A AA                      	stosb
  1534 0000094B 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1535 0000094D AA                      	stosb
  1536                                  	;
  1537 0000094E 5A                      	pop	edx
  1538 0000094F 59                      	pop	ecx
  1539                                  	;
  1540 00000950 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1541                                  			; white (F) forecolor
  1542 00000952 BE[FA630000]            	mov	esi, exc_msg ; message offset
  1543                                  	;
  1544 00000957 EB11                    	jmp	short piemsg
  1545                                  	;
  1546                                          ;add    dword [scr_row], 0A0h
  1547                                          ;mov    edi, [scr_row]
  1548                                          ;
  1549                                  	;call 	printk
  1550                                  	;
  1551                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1552                                  	;out	20h, al	; 8259 PORT
  1553                                  	;
  1554                                  	;pop	es
  1555                                  	;pop	ds
  1556                                  	;pop	edi
  1557                                  	;pop	esi
  1558                                  	;pop 	eax
  1559                                  	;iret
  1560                                  	
  1561                                  	; 28/08/2015
  1562                                  	; 23/02/2015
  1563                                  	; 20/08/2014
  1564                                  ignore_int:
  1565 00000959 50                      	push	eax
  1566 0000095A 53                      	push	ebx ; 23/02/2015
  1567 0000095B 56                      	push	esi
  1568 0000095C 57                      	push	edi
  1569 0000095D 1E                      	push 	ds
  1570 0000095E 06                      	push 	es
  1571                                  	; 28/08/2015
  1572 0000095F 0F20D8                  	mov	eax, cr3
  1573 00000962 50                      	push	eax ; (*) page directory
  1574                                  	;
  1575 00000963 B467                    	mov	ah, 67h	; brown (6) background, 
  1576                                  			; light gray (7) forecolor
  1577 00000965 BE[B8630000]            	mov	esi, int_msg ; message offset
  1578                                  piemsg:
  1579                                          ; 27/08/2014
  1580 0000096A 8105[7C630000]A000-             add     dword [scr_row], 0A0h
  1580 00000972 0000               
  1581 00000974 8B3D[7C630000]                  mov     edi, [scr_row]
  1582                                          ;
  1583 0000097A E8B6FCFFFF              	call 	printk
  1584                                  	;
  1585                                  	; 23/02/2015
  1586 0000097F B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1587 00000981 E6A0                    	out	0A0h, al ; the 2nd 8259
  1588                                  iiretp: ; 01/09/2015
  1589                                  	; 28/08/2015
  1590 00000983 58                      	pop	eax ; (*) page directory
  1591 00000984 0F22D8                  	mov	cr3, eax
  1592                                  	;
  1593                                  iiret:
  1594                                  	; 22/08/2014
  1595 00000987 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1596 00000989 E620                    	out	20h, al	; 8259 PORT
  1597                                  	;
  1598 0000098B 07                      	pop	es
  1599 0000098C 1F                      	pop	ds
  1600 0000098D 5F                      	pop	edi
  1601 0000098E 5E                      	pop	esi
  1602 0000098F 5B                      	pop	ebx ; 29/08/2014
  1603 00000990 58                      	pop 	eax
  1604 00000991 CF                      	iretd
  1605                                  
  1606                                  	; 23/02/2022
  1607                                  	; 26/02/2015
  1608                                  	; 07/09/2014
  1609                                  	; 25/08/2014
  1610                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1611                                  	; 22/08/2014
  1612 00000992 50                      	push	eax
  1613 00000993 53                      	push	ebx ; 29/08/2014
  1614 00000994 56                      	push	esi
  1615 00000995 57                      	push	edi
  1616 00000996 1E                      	push 	ds
  1617 00000997 06                      	push 	es
  1618                                  	;
  1619 00000998 B810000000              	mov	eax, KDATA
  1620 0000099D 8ED8                    	mov	ds, ax
  1621 0000099F 8EC0                    	mov	es, ax
  1622                                  	;
  1623                                  	; 25/08/2014
  1624                                  	;call	rtc_p
  1625                                  	; 23/02/2022
  1626 000009A1 FF15[F4060000]          	call	[x_rtci]
  1627                                  	;
  1628                                  	; 22/02/2015 - dsectpm.s
  1629                                  	; [ source: http://wiki.osdev.org/RTC ]
  1630                                  	; read status register C to complete procedure
  1631                                  	;(it is needed to get a next IRQ 8) 
  1632 000009A7 B00C                    	mov	al, 0Ch ; 
  1633 000009A9 E670                    	out	70h, al ; select register C
  1634 000009AB 90                      	nop
  1635 000009AC E471                    	in	al, 71h ; just throw away contents
  1636                                  	; 22/02/2015
  1637 000009AE B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1638 000009B0 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1639                                  	;
  1640 000009B2 EBD3                    	jmp	short iiret	
  1641                                  
  1642                                  	; 22/08/2014
  1643                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1644                                  	; (INT 1Ah)
  1645                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1646                                  time_of_day:
  1647 000009B4 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1648 000009B9 726F                            jc      short rtc_retn 
  1649 000009BB B000                    	mov	al, CMOS_SECONDS
  1650 000009BD E847010000              	call	CMOS_READ
  1651 000009C2 A2[9C680000]            	mov	[time_seconds], al 
  1652 000009C7 B002                    	mov	al, CMOS_MINUTES
  1653 000009C9 E83B010000              	call	CMOS_READ
  1654 000009CE A2[9D680000]            	mov	[time_minutes], al 
  1655 000009D3 B004                    	mov	al, CMOS_HOURS
  1656 000009D5 E82F010000              	call	CMOS_READ
  1657 000009DA A2[9E680000]                    mov     [time_hours], al
  1658 000009DF B006                    	mov	al, CMOS_DAY_WEEK 
  1659 000009E1 E823010000              	call	CMOS_READ
  1660 000009E6 A2[9F680000]            	mov	[date_wday], al
  1661 000009EB B007                     	mov	al, CMOS_DAY_MONTH
  1662 000009ED E817010000              	call	CMOS_READ
  1663 000009F2 A2[A0680000]            	mov	[date_day], al
  1664 000009F7 B008                    	mov	al, CMOS_MONTH
  1665 000009F9 E80B010000              	call	CMOS_READ
  1666 000009FE A2[A1680000]            	mov	[date_month], al
  1667 00000A03 B009                    	mov	al, CMOS_YEAR
  1668 00000A05 E8FF000000              	call	CMOS_READ
  1669 00000A0A A2[A2680000]            	mov	[date_year], al
  1670 00000A0F B032                    	mov	al, CMOS_CENTURY
  1671 00000A11 E8F3000000              	call	CMOS_READ
  1672 00000A16 A2[A3680000]            	mov	[date_century], al
  1673                                  	;
  1674 00000A1B B000                    	mov	al, CMOS_SECONDS
  1675 00000A1D E8E7000000              	call 	CMOS_READ
  1676 00000A22 3A05[9C680000]          	cmp	al, [time_seconds]
  1677 00000A28 758A                    	jne	short time_of_day
  1678                                  
  1679                                  rtc_retn:
  1680 00000A2A C3                      	retn
  1681                                  
  1682                                  rtci_default:
  1683                                  	; 23/02/2022 (Temporary!)
  1684                                  	; (default real time clock handler in multitasking mode)
  1685                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1686 00000A2B FF05[E0680000]          	inc	dword [rtc_ticks] ; real time clock counter
  1687                                  			; (not used in anywhere of kernel for now!)
  1688 00000A31 C3                      	retn
  1689                                  
  1690                                  rtc_p:
  1691                                  	; 27/12/2021 (Retro UNIX 386 v1.2)
  1692                                  	; 07/09/2014
  1693                                  	; 29/08/2014
  1694                                  	; 27/08/2014
  1695                                  	; 25/08/2014
  1696                                   	; Print Real Time Clock content
  1697                                  	;
  1698                                  	;
  1699 00000A32 E87DFFFFFF              	call	time_of_day
  1700 00000A37 72F1                    	jc	short rtc_retn
  1701                                  	;
  1702 00000A39 3A05[6C640000]          	cmp	al, [ptime_seconds]
  1703 00000A3F 74E9                            je      short rtc_retn ; 29/08/2014
  1704                                  	;
  1705 00000A41 A2[6C640000]            	mov	[ptime_seconds], al
  1706                                  	;
  1707 00000A46 A0[A3680000]            	mov	al, [date_century]
  1708 00000A4B E8EA000000              	call	bcd_to_ascii
  1709 00000A50 66A3[39640000]          	mov	[datestr+6], ax
  1710 00000A56 A0[A2680000]            	mov	al, [date_year]
  1711 00000A5B E8DA000000              	call	bcd_to_ascii
  1712 00000A60 66A3[3B640000]          	mov	[datestr+8], ax
  1713 00000A66 A0[A1680000]            	mov	al, [date_month]
  1714 00000A6B E8CA000000              	call	bcd_to_ascii
  1715 00000A70 66A3[36640000]          	mov	[datestr+3], ax
  1716 00000A76 A0[A0680000]            	mov	al, [date_day]
  1717 00000A7B E8BA000000              	call	bcd_to_ascii
  1718 00000A80 66A3[33640000]          	mov	[datestr], ax
  1719                                  	;
  1720 00000A86 0FB61D[9F680000]        	movzx	ebx, byte [date_wday]
  1721 00000A8D C0E302                  	shl 	bl, 2
  1722 00000A90 81C3[4C640000]          	add	ebx, daytmp
  1723 00000A96 8B03                    	mov	eax, [ebx]
  1724 00000A98 A3[3E640000]            	mov	[daystr], eax
  1725                                  	;
  1726 00000A9D A0[9E680000]            	mov	al, [time_hours]
  1727 00000AA2 E893000000              	call	bcd_to_ascii
  1728 00000AA7 66A3[42640000]          	mov	[timestr], ax
  1729 00000AAD A0[9D680000]            	mov	al, [time_minutes]
  1730 00000AB2 E883000000              	call	bcd_to_ascii
  1731 00000AB7 66A3[45640000]          	mov	[timestr+3], ax
  1732 00000ABD A0[9C680000]            	mov	al, [time_seconds]
  1733 00000AC2 E873000000              	call	bcd_to_ascii
  1734 00000AC7 66A3[48640000]          	mov	[timestr+6], ax
  1735                                  	;		
  1736 00000ACD BE[21640000]            	mov	esi, rtc_msg ; message offset
  1737                                  	; 23/02/2015
  1738 00000AD2 52                      	push	edx
  1739 00000AD3 51                      	push	ecx
  1740                                  	; 07/09/2014
  1741                                  	;mov	bx, 2	; Video page 2
  1742                                  	; 27/12/2021
  1743 00000AD4 29DB                    	sub	ebx, ebx
  1744                                  	;mov	bl, 2
  1745                                  	; 15/02/2022
  1746 00000AD6 B307                    	mov	bl, 7	; Video page 7
  1747                                  prtmsg:
  1748 00000AD8 AC                      	lodsb
  1749 00000AD9 08C0                    	or	al, al
  1750 00000ADB 740D                    	jz	short prtmsg_ok
  1751 00000ADD 56                      	push	esi
  1752                                  	;push	bx
  1753 00000ADE 53                              push	ebx ; 27/12/2021
  1754 00000ADF B43F                    	mov	ah, 3Fh	; cyan (6) background, 
  1755                                  			; white (F) forecolor
  1756 00000AE1 E8BB080000              	call 	write_tty
  1757                                  	;pop	bx
  1758 00000AE6 5B                      	pop	ebx ; 27/12/2021
  1759 00000AE7 5E                      	pop	esi
  1760 00000AE8 EBEE                    	jmp	short prtmsg
  1761                                  	;
  1762                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1763                                  	;call	printk
  1764                                  prtmsg_ok:
  1765                                  	; 07/09/2014
  1766                                  	;xor	dx, dx		; column 0, row 0
  1767                                  	; 27/12/2021
  1768 00000AEA 31D2                    	xor	edx, edx
  1769 00000AEC E8BA090000              	call	set_cpos	; set curspor position to 0,0 
  1770                                  	; 23/02/2015
  1771 00000AF1 59                      	pop	ecx
  1772 00000AF2 5A                      	pop	edx
  1773 00000AF3 C3                      	retn
  1774                                  
  1775                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1776                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1777                                  default_irq7:
  1778                                  	; 04/12/2021
  1779                                  	;push	ax
  1780 00000AF4 50                      	push	eax
  1781 00000AF5 B00B                    	mov	al, 0Bh  ; In-Service register
  1782 00000AF7 E620                    	out	20h, al
  1783 00000AF9 EB00                            jmp short $+2
  1784 00000AFB EB00                    	jmp short $+2
  1785 00000AFD E420                    	in	al, 20h
  1786 00000AFF 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1787 00000B01 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1788 00000B03 B020                            mov     al, 20h ; EOI
  1789 00000B05 E620                    	out	20h, al 
  1790                                  irq7_iret:
  1791                                  	;pop	ax
  1792                                  	; 04/12/2021
  1793 00000B07 58                      	pop	eax
  1794 00000B08 CF                      	iretd
  1795                                  	
  1796                                  	; 04/12/2021
  1797                                  	; 22/08/2014
  1798                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1799                                  CMOS_READ:
  1800 00000B09 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1801 00000B0A D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1802 00000B0C F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1803 00000B0D D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1804 00000B0F FA                      	cli		; DISABLE INTERRUPTS
  1805 00000B10 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1806 00000B12 90                      	nop		; I/O DELAY
  1807 00000B13 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1808                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1809                                  	; 04/12/2021
  1810 00000B15 50                      	push	eax
  1811                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1812                                  		     ; ----- 10/06/85 (test4.asm)
  1813 00000B16 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1814                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1815 00000B18 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1816 00000B1A E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1817                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1818                                  	; 04/12/2021
  1819 00000B1C 58                      	pop	eax
  1820 00000B1D 9D                      	popf	
  1821 00000B1E C3                      	retn		; RETURN WITH FLAGS RESTORED
  1822                                  
  1823                                  	; 22/08/2014
  1824                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1825                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1826 00000B1F 51                      	push	ecx
  1827 00000B20 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1828                                  		; mov cx, 800	
  1829                                  UPD_10:
  1830 00000B25 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1831 00000B27 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1832 00000B28 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1833 00000B2D A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1834 00000B2F 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1835 00000B31 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1836 00000B32 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1837 00000B34 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1838                                  		; xor ax, ax
  1839 00000B36 F9                      	stc				; SET CARRY FOR ERROR
  1840                                  UPD_90:
  1841 00000B37 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1842 00000B38 FA                      	cli				; INTERRUPTS OFF DURING SET
  1843 00000B39 C3                      	retn				; RETURN WITH CY FLAG SET
  1844                                  
  1845                                  bcd_to_ascii:
  1846                                  	; 25/08/2014
  1847                                  	; INPUT ->
  1848                                  	;	al = Packed BCD number
  1849                                  	; OUTPUT ->
  1850                                  	;	ax  = ASCII word/number
  1851                                  	;
  1852                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1853                                  	;
  1854 00000B3A D410                    	db	0D4h, 10h		; Undocumented inst. AAM
  1855                                  					; AH = AL / 10h
  1856                                  					; AL = AL MOD 10h
  1857 00000B3C 660D3030                	or	ax, '00'		; Make it ASCII based
  1858                                  
  1859 00000B40 86E0                            xchg	ah, al 
  1860                                  	
  1861 00000B42 C3                      	retn	
  1862                                  	
  1863                                  
  1864                                  %include 'keyboard.s' ; 07/03/2015
  1865                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1866                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1867                              <1> ; ****************************************************************************
  1868                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - KEYBOARD.INC
  1869                              <1> ; Last Modification: 11/06/2022
  1870                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1871                              <1> ;
  1872                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1873                              <1> 
  1874                              <1> ; 23/02/2022
  1875                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  1876                              <1> ; 30/06/2015
  1877                              <1> ; 11/03/2015
  1878                              <1> ; 28/02/2015
  1879                              <1> ; 25/02/2015
  1880                              <1> ; 20/02/2015
  1881                              <1> ; 18/02/2015
  1882                              <1> ; 03/12/2014
  1883                              <1> ; 07/09/2014
  1884                              <1> ; KEYBOARD INTERRUPT HANDLER
  1885                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1886                              <1> 
  1887                              <1> ;getch:
  1888                              <1> ;	; 18/02/2015
  1889                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1890                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1891                              <1> ;	; routine, later... (multi tasking ability)
  1892                              <1> ;	; 28/02/2015
  1893                              <1> ;	sti	; enable interrupts
  1894                              <1> ;	;
  1895                              <1> ;	;push	esi
  1896                              <1> ;	;push	ebx
  1897                              <1> ;	;xor	ebx, ebx
  1898                              <1> ;	;mov	bl, [ptty]  ; active_page
  1899                              <1> ;	;mov	esi, ebx
  1900                              <1> ;	;shl 	si, 1
  1901                              <1> ;	;add	esi, ttychr
  1902                              <1> ;getch_1:
  1903                              <1> ;	;mov	ax, [esi]
  1904                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1905                              <1> ;	and	ax, ax
  1906                              <1> ;	jz	short getch_2
  1907                              <1> ;	mov	word [ttychr], 0
  1908                              <1> ;	;mov	word [esi], 0
  1909                              <1> ;	;pop	ebx
  1910                              <1> ;	;pop	esi
  1911                              <1> ;	retn
  1912                              <1> ;getch_2:
  1913                              <1> ;	hlt	; not proper for multi tasking!
  1914                              <1> ;		; (temporary halt for now)
  1915                              <1> ;		; 'sleep' on tty 
  1916                              <1> ;		; will (must) be located here		
  1917                              <1> ;	nop
  1918                              <1> ;	jmp	short getch_1
  1919                              <1> 
  1920                              <1> keyb_int:
  1921                              <1> 	; 23/02/2022
  1922                              <1> 	; 30/06/2015
  1923                              <1> 	; 25/02/2015
  1924                              <1> 	; 20/02/2015
  1925                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1926                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1927                              <1> 	; 30/06/2014
  1928                              <1> 	; 10/05/2013	
  1929                              <1>       	; Retro Unix 8086 v1 feature only!
  1930                              <1> 	; 03/03/2014
  1931                              <1> 	
  1932 00000B43 1E                  <1> 	push	ds
  1933 00000B44 53                  <1> 	push	ebx
  1934 00000B45 50                  <1> 	push	eax
  1935                              <1> 	;
  1936                              <1> 	; 23/02/2022
  1937 00000B46 9C                  <1> 	pushfd
  1938 00000B47 0E                  <1> 	push	cs
  1939                              <1> 	;mov	ax, KDATA
  1940 00000B48 31C0                <1> 	xor	eax, eax
  1941 00000B4A B010                <1> 	mov	al, KDATA
  1942 00000B4C 8ED8                <1> 	mov	ds, ax
  1943                              <1> 	;
  1944                              <1> 	;pushfd
  1945                              <1> 	;push	cs
  1946 00000B4E E810020000          <1> 	call	kb_int   ; int_09h
  1947                              <1> 	;
  1948 00000B53 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1949                              <1> 	;call	getc
  1950 00000B55 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1951 00000B5A 744E                <1> 	jz	short keyb_int4
  1952                              <1> 	;
  1953 00000B5C B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1954                              <1> 	;call	getc
  1955 00000B5E E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1956                              <1> 	;
  1957                              <1> 	; 20/02/2015
  1958 00000B63 0FB61D[56680000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1959                              <1> 	;
  1960 00000B6A 20C0                <1> 	and 	al, al
  1961 00000B6C 751D                <1> 	jnz	short keyb_int1
  1962                              <1> 	;
  1963 00000B6E 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1964 00000B71 7218                <1> 	jb	short keyb_int1
  1965 00000B73 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1966 00000B76 7713                <1> 	ja	short keyb_int1
  1967                              <1> 	;
  1968 00000B78 88D8                <1> 	mov	al, bl
  1969 00000B7A 0468                <1> 	add	al, 68h
  1970 00000B7C 38E0                <1> 	cmp	al, ah
  1971 00000B7E 7409                <1> 	je	short keyb_int0
  1972 00000B80 88E0                <1> 	mov	al, ah
  1973 00000B82 2C68                <1> 	sub	al, 68h
  1974 00000B84 E8370A0000          <1> 	call	tty_sw
  1975                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1976                              <1> keyb_int0: ; 30/06/2015
  1977                              <1> 	;xor	ax, ax
  1978                              <1> 	; 23/02/2022
  1979 00000B89 31C0                <1> 	xor	eax, eax
  1980                              <1> keyb_int1:
  1981 00000B8B D0E3                <1> 	shl	bl, 1
  1982 00000B8D 81C3[58680000]      <1> 	add	ebx, ttychr
  1983                              <1> 	;
  1984                              <1> 	;23/02/2022
  1985 00000B93 09C0                <1> 	or	eax, eax
  1986                              <1> 	;or	ax, ax
  1987 00000B95 7406                <1> 	jz	short keyb_int2
  1988                              <1> 	;
  1989 00000B97 66833B00            <1> 	cmp 	word [ebx], 0
  1990 00000B9B 7703                <1>         ja      short keyb_int3 
  1991                              <1> keyb_int2:
  1992 00000B9D 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1993                              <1> 			   ; and scan code of the character
  1994                              <1> 			   ; for current tty (or last tty
  1995                              <1> 			   ; just before tty switch).
  1996                              <1> keyb_int3:
  1997 00000BA0 A0[56680000]        <1>         mov     al, [ptty]
  1998 00000BA5 E8B53C0000          <1> 	call	wakeup
  1999                              <1> 	;
  2000                              <1> keyb_int4:
  2001 00000BAA 58                  <1> 	pop	eax
  2002 00000BAB 5B                  <1> 	pop	ebx
  2003 00000BAC 1F                  <1> 	pop	ds
  2004 00000BAD CF                  <1> 	iret
  2005                              <1> 
  2006                              <1> ; 18/02/2015
  2007                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2008                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2009                              <1> ; scancode and ascii code of the character 
  2010                              <1> ; in the tty input (ttychr) buffer. 
  2011                              <1> ; Test procedures must call 'getch' for tty input
  2012                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2013                              <1> ; due to infinite (key press) waiting loop.
  2014                              <1> ; 
  2015                              <1> ; 03/12/2014
  2016                              <1> ; 26/08/2014
  2017                              <1> ; KEYBOARD I/O
  2018                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2019                              <1> 
  2020                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2021                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2022                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2023                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2024                              <1> 
  2025                              <1> int_16h: ; 30/06/2015
  2026                              <1> ;getc:
  2027 00000BAE 9C                  <1> 	pushfd	; 28/08/2014
  2028 00000BAF 0E                  <1> 	push 	cs
  2029 00000BB0 E826000000          <1> 	call 	getc_int
  2030 00000BB5 C3                  <1> 	retn
  2031                              <1> 
  2032                              <1> ; 05/12/2021
  2033                              <1> 
  2034                              <1> 	;-----	SHIFT STATUS
  2035                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2036 00000BB6 8A25[84620000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2037 00000BBC 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2038                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2039                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2040 00000BBF C0E405              <1>         shl	ah, 5
  2041 00000BC2 A0[84620000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2042 00000BC7 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2043 00000BC9 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2044 00000BCB A0[86620000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2045 00000BD0 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2046 00000BD2 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2047                              <1> _K3:
  2048 00000BD4 A0[83620000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2049 00000BD9 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2050                              <1> 
  2051                              <1> getc_int:
  2052                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2053                              <1> 	; 28/02/2015
  2054                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2055                              <1> 	;	      instead of pc-at bios - 1985-)
  2056                              <1> 	; 28/08/2014 (_k1d)
  2057                              <1> 	; 30/06/2014
  2058                              <1> 	; 03/03/2014
  2059                              <1> 	; 28/02/2014
  2060                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2061                              <1> 	; rombios source code (21/04/1986)
  2062                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2063                              <1> 	;
  2064                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2065                              <1> 	;
  2066                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2067                              <1> 	; KEYBOARD I/O								      :
  2068                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2069                              <1> 	; INPUT									      :
  2070                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2071                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2072                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2073                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2074                              <1> 	;-----------------------------------------------------------------------------:
  2075                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2076                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2077                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2078                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2079                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2080                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2081                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2082                              <1> 	;-----------------------------------------------------------------------------:	
  2083                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2084                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2085                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2086                              <1> 	;-----------------------------------------------------------------------------:	
  2087                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2088                              <1> 	;	      (AL) = 05H                                                      :
  2089                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2090                              <1> 	;		       							      :
  2091                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2092                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2093                              <1> 	;                     --------------------------------------------            :
  2094                              <1> 	;			00H        30.0        10H        7.5                 :
  2095                              <1> 	;			01H        26.7        11H        6.7                 :
  2096                              <1> 	;			02H        24.0        12H        6.0                 :
  2097                              <1> 	;			03H        21.8        13H        5.5                 :
  2098                              <1> 	;			04H        20.0        14H        5.0                 :
  2099                              <1> 	;			05H        18.5        15H        4.6                 :
  2100                              <1> 	;			06H        17.1        16H        4.3                 :
  2101                              <1> 	;			07H        16.0        17H        4.0                 :
  2102                              <1> 	;			08H        15.0        18H        3.7                 :
  2103                              <1> 	;			09H        13.3        19H        3.3                 :
  2104                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2105                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2106                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2107                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2108                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2109                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2110                              <1> 	;									      :
  2111                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2112                              <1> 	;		       							      :
  2113                              <1> 	;                     REGISTER     DELAY                                      :
  2114                              <1> 	;                      VALUE       VALUE                                      :
  2115                              <1> 	;                     ------------------                                      :
  2116                              <1> 	;			00H        250 ms                                     :
  2117                              <1> 	;			01H        500 ms                                     :
  2118                              <1> 	;			02H        750 ms                                     :
  2119                              <1> 	;			03H       1000 ms                                     :
  2120                              <1> 	;-----------------------------------------------------------------------------:
  2121                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2122                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2123                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2124                              <1> 	;		           (CH) = SCAN CODE                                   :
  2125                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2126                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2127                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2128                              <1> 	;-----------------------------------------------------------------------------:		
  2129                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2130                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2131                              <1> 	;-----------------------------------------------------------------------------:
  2132                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2133                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2134                              <1> 	;-----------------------------------------------------------------------------:	
  2135                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2136                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2137                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2138                              <1> 	; OUTPUT					                              :
  2139                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2140                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2141                              <1> 	;------------------------------------------------------------------------------
  2142                              <1> 	
  2143 00000BDB FB                  <1> 	sti				; INTERRUPTS BACK ON
  2144 00000BDC 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2145 00000BDD 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2146                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2147 00000BDE 66BB1000            <1>         mov     bx, KDATA 
  2148 00000BE2 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2149 00000BE4 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2150 00000BE6 742D                <1> 	jz	short _K1		; ASCII_READ
  2151 00000BE8 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2152 00000BEA 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2153 00000BEC FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2154 00000BEE 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2155 00000BF0 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2156 00000BF2 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2157 00000BF4 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2158 00000BF7 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2159                              <1> _KIO1:	
  2160 00000BF9 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2161 00000BFC 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2162 00000BFE FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2163 00000C00 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2164 00000C02 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2165 00000C04 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2166                              <1> _KIO_EXIT:
  2167                              <1> 	;pop	ecx			; RECOVER REGISTER
  2168 00000C06 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2169 00000C07 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2170 00000C08 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2171                              <1> 
  2172                              <1> 	;-----	ASCII CHARACTER
  2173                              <1> _K1E:	
  2174 00000C09 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2175 00000C0E E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2176 00000C13 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2177                              <1> _K1:	
  2178 00000C15 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2179 00000C1A E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2180 00000C1F 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2181                              <1> _K1A:
  2182 00000C21 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2183                              <1> 
  2184                              <1> 	;-----	ASCII STATUS
  2185                              <1> _K2E:	
  2186 00000C23 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2187 00000C28 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2188 00000C2A 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2189 00000C2B E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2190 00000C30 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2191                              <1> _K2:	
  2192 00000C32 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2193 00000C37 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2194 00000C39 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2195 00000C3A E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2196 00000C3F 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2197 00000C41 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2198 00000C42 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2199 00000C47 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2200                              <1> _K2A:
  2201 00000C49 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2202                              <1> _K2B:
  2203                              <1> 	;pop	ecx			; RECOVER REGISTER
  2204 00000C4A 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2205 00000C4B 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2206 00000C4C CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2207                              <1> 
  2208                              <1> ; 05/12/2021
  2209                              <1> ;	;-----	SHIFT STATUS
  2210                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2211                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2212                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2213                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2214                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2215                              <1> ;       shl	ah, 5
  2216                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2217                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2218                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2219                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2220                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2221                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2222                              <1> ;_K3:
  2223                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2224                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2225                              <1> 
  2226                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2227                              <1> _K300:
  2228 00000C4F 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2229 00000C51 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2230 00000C53 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2231 00000C56 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2232 00000C58 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2233 00000C5B 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2234 00000C5D B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2235 00000C5F E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2236                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2237                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2238 00000C64 C0E705              <1> 	shl	bh, 5
  2239 00000C67 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2240 00000C69 08F8                <1> 	or	al, bh			; AND DELAY
  2241 00000C6B E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2242 00000C70 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2243                              <1> 
  2244                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2245                              <1> _K500:
  2246 00000C72 56                  <1> 	push	esi			; SAVE SI (esi)
  2247 00000C73 FA                  <1> 	cli				; 
  2248 00000C74 8B1D[94620000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2249 00000C7A 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2250 00000C7C E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2251 00000C81 3B1D[90620000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2252 00000C87 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2253 00000C89 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2254 00000C8C 891D[94620000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2255 00000C92 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2256 00000C94 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2257                              <1> _K502:
  2258 00000C96 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2259                              <1> _K504:
  2260 00000C98 FB                  <1> 	sti				
  2261 00000C99 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2262 00000C9A E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2263                              <1> 
  2264                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2265                              <1> _K1S:
  2266 00000C9F FA                  <1> 	cli	; 03/12/2014
  2267 00000CA0 8B1D[90620000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2268 00000CA6 3B1D[94620000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2269                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2270 00000CAC 750F                <1> 	jne	short _k1x ; 03/12/2014
  2271                              <1> 	;
  2272                              <1> 	; 03/12/2014
  2273                              <1> 	; 28/08/2014
  2274                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2275                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2276                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2277                              <1> _K1T:                                   ; ASCII READ
  2278 00000CAE FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2279 00000CAF 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2280                              <1> _K1U:	
  2281 00000CB0 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2282 00000CB1 8B1D[90620000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2283 00000CB7 3B1D[94620000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2284                              <1> _k1x:
  2285 00000CBD 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2286 00000CBE 9C                  <1> 	pushf				; SAVE FLAGS
  2287 00000CBF E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2288 00000CC4 8A1D[85620000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2289 00000CCA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2290 00000CCC 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2291 00000CCF 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2292 00000CD1 E86A060000          <1> 	call	SND_LED1
  2293 00000CD6 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2294                              <1> _K1V:
  2295 00000CD7 9D                  <1> 	popf				; RESTORE FLAGS
  2296 00000CD8 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2297 00000CD9 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2298                              <1> 	;
  2299 00000CDB 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2300 00000CDE E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2301 00000CE3 891D[90620000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2302 00000CE9 C3                  <1> 	retn				; RETURN
  2303                              <1> 
  2304                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2305                              <1> _K2S:
  2306 00000CEA FA                  <1> 	cli				; INTERRUPTS OFF
  2307 00000CEB 8B1D[90620000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2308 00000CF1 3B1D[94620000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2309 00000CF7 668B03              <1> 	mov	ax, [ebx]
  2310 00000CFA 9C                  <1> 	pushf				; SAVE FLAGS
  2311                              <1> 	;push	ax			; SAVE CODE
  2312                              <1> 	; 05/12/2021
  2313 00000CFB 50                  <1> 	push	eax
  2314 00000CFC E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2315 00000D01 8A1D[85620000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2316 00000D07 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2317 00000D09 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2318 00000D0C 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2319 00000D0E E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2320                              <1> _K2T:
  2321                              <1> 	;pop	ax			; RESTORE CODE
  2322                              <1> 	; 05/12/2021
  2323 00000D13 58                  <1> 	pop	eax
  2324 00000D14 9D                  <1> 	popf				; RESTORE FLAGS
  2325 00000D15 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2326 00000D16 C3                  <1> 	retn				; RETURN
  2327                              <1> 
  2328                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2329                              <1> _KIO_E_XLAT:
  2330 00000D17 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2331 00000D19 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2332 00000D1B 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2333 00000D1D 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2334 00000D1F 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2335                              <1> _KIO_E_RET:				
  2336 00000D21 C3                  <1> 	retn				; GO BACK
  2337                              <1> 
  2338                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2339                              <1> _KIO_S_XLAT:
  2340 00000D22 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2341 00000D25 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2342 00000D27 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2343 00000D29 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2344 00000D2B 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2345 00000D2D 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2346 00000D2F B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2347                              <1> _kio_ret: ; 03/12/2014
  2348 00000D31 F8                  <1> 	clc
  2349 00000D32 C3                  <1> 	retn
  2350                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2351                              <1> _KIO_S1:				
  2352 00000D33 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2353                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2354 00000D35 C3                  <1> 	retn
  2355                              <1> _KIO_S2:		
  2356 00000D36 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2357 00000D39 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2358 00000D3B 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2359 00000D3D 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2360 00000D3F 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2361 00000D41 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2362 00000D43 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2363                              <1> _KIO_S3:
  2364 00000D45 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2365                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2366 00000D47 75E8                <1> 	jne	short _kio_ret
  2367 00000D49 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2368 00000D4B 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2369 00000D4D 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2370                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2371                              <1> _KIO_USE:
  2372                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2373 00000D4F C3                  <1> 	retn				; RETURN	
  2374                              <1> _KIO_DIS:
  2375 00000D50 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2376 00000D51 C3                  <1> 	retn				; RETURN
  2377                              <1> 
  2378                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2379                              <1> _K4:    
  2380 00000D52 43                  <1> 	inc     ebx
  2381 00000D53 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2382 00000D54 3B1D[8C620000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2383                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2384 00000D5A 7206                <1> 	jb	short _K5
  2385 00000D5C 8B1D[88620000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2386                              <1> _K5:
  2387 00000D62 C3                  <1> 	retn
  2388                              <1> 
  2389                              <1> ; 20/02/2015
  2390                              <1> ; 05/12/2014
  2391                              <1> ; 26/08/2014
  2392                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2393                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2394                              <1> ;
  2395                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2396                              <1> ; rombios source code (06/10/1985)
  2397                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2398                              <1> 
  2399                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2400                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2401                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2402                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2403                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2404                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2405                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2406                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2407                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2408                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2409                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2410                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2411                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2412                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2413                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2414                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2415                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2416                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2417                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2418                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2419                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2420                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2421                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2422                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2423                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2424                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2425                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2426                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2427                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2428                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2429                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2430                              <1> F11_M		equ	87		; F11 KEY MAKE
  2431                              <1> F12_M		equ	88		; F12 KEY MAKE
  2432                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2433                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2434                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2435                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2436                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2437                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2438                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2439                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2440                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2441                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2442                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2443                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2444                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2445                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2446                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2447                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2448                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2449                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2450                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2451                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2452                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2453                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2454                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2455                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2456                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2457                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2458                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2459                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2460                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2461                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2462                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2463                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2464                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2465                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2466                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2467                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2468                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2469                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2470                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2471                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2472                              <1> ;
  2473                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2474                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2475                              <1> INTA00		equ	020h		; 8259 PORT
  2476                              <1> 
  2477                              <1> 
  2478                              <1> kb_int:
  2479                              <1> 
  2480                              <1> ; 11/06/2022
  2481                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2482                              <1> ; 17/10/2015 ('ctrlbrk') 
  2483                              <1> ; 05/12/2014
  2484                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2485                              <1> 	;	      instead of pc-at bios - 1985-)
  2486                              <1> ; 26/08/2014
  2487                              <1> ;
  2488                              <1> ; 03/06/86  KEYBOARD BIOS
  2489                              <1> ;
  2490                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2491                              <1> ;										;
  2492                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2493                              <1> ;										;
  2494                              <1> ;--------------------------------------------------------------------------------
  2495                              <1> 
  2496                              <1> KB_INT_1:
  2497 00000D63 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2498                              <1> 	;push	ebp
  2499 00000D64 50                  <1> 	push	eax
  2500 00000D65 53                  <1> 	push	ebx
  2501 00000D66 51                  <1> 	push	ecx
  2502 00000D67 52                  <1> 	push	edx
  2503 00000D68 56                  <1> 	push	esi
  2504 00000D69 57                  <1> 	push	edi
  2505 00000D6A 1E                  <1> 	push	ds
  2506 00000D6B 06                  <1> 	push	es
  2507 00000D6C FC                  <1> 	cld				; FORWARD DIRECTION
  2508 00000D6D 66B81000            <1> 	mov	ax, KDATA
  2509 00000D71 8ED8                <1> 	mov	ds, ax
  2510 00000D73 8EC0                <1> 	mov	es, ax
  2511                              <1> 	;
  2512                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2513 00000D75 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2514 00000D77 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2515 00000D7C FA                  <1> 	cli				; DISABLE INTERRUPTS
  2516 00000D7D B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2517                              <1> KB_INT_01:
  2518 00000D82 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2519 00000D84 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2520 00000D86 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2521                              <1> 	;
  2522                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2523 00000D88 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2524                              <1> 	;
  2525                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2526                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2527                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2528                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2529                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2530                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2531                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2532                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2533                              <1> 	;
  2534                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2535                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2536 00000D8A FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2537 00000D8B 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2538 00000D8D 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2539                              <1> 	;
  2540                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2541 00000D8F 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2542 00000D91 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2543                              <1> 	;
  2544                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2545 00000D93 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2546 00000D94 800D[85620000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2547 00000D9B E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2548                              <1> 	;
  2549                              <1> 	;-----	RESEND THE LAST BYTE
  2550                              <1> KB_INT_4:
  2551 00000DA0 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2552 00000DA1 800D[85620000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2553 00000DA8 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2554                              <1> 	;
  2555                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2556                              <1> KB_INT_2:
  2557                              <1> 	;push 	ax			; SAVE DATA IN
  2558                              <1> 	; 05/12/2021
  2559 00000DAD 50                  <1> 	push	eax
  2560 00000DAE E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2561 00000DB3 8A1D[85620000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2562 00000DB9 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2563 00000DBB 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2564 00000DBE 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2565 00000DC0 E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2566                              <1> UP0:
  2567                              <1> 	;pop	ax			; RESTORE DATA IN
  2568                              <1> 	; 05/12/2021
  2569 00000DC5 58                  <1> 	pop	eax
  2570                              <1> ;------------------------------------------------------------------------
  2571                              <1> ;	START OF KEY PROCESSING						;
  2572                              <1> ;------------------------------------------------------------------------
  2573 00000DC6 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2574                              <1> 	;
  2575                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2576 00000DC8 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2577                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2578                              <1> 	; 05/12/2021
  2579 00000DCA 7505                <1> 	jne	short K16
  2580 00000DCC E9E9040000          <1> 	jmp	K62
  2581                              <1> K16:	
  2582 00000DD1 8A3D[86620000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2583                              <1> 	;
  2584                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2585 00000DD7 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2586 00000DDA 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2587 00000DDC 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2588 00000DDE 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2589 00000DE0 7507                <1> 	jne	short RST_RD_ID
  2590 00000DE2 800D[86620000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2591                              <1> RST_RD_ID:
  2592 00000DE9 8025[86620000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2593 00000DF0 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2594                              <1> 	; 05/12/2021
  2595                              <1> 	;jmp	K26
  2596                              <1> 	;
  2597                              <1> TST_ID_2:
  2598 00000DF2 8025[86620000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2599 00000DF9 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2600 00000DFB 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2601 00000DFD 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2602 00000DFF 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2603                              <1> 	; 05/12/2021
  2604                              <1> 	;jne	K26
  2605                              <1> 	;
  2606                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2607 00000E01 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2608 00000E04 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2609 00000E06 800D[83620000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2610 00000E0D E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2611                              <1> KX_BIT:
  2612 00000E12 800D[86620000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2613 00000E19 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2614                              <1> 	;
  2615                              <1> NOT_ID:
  2616 00000E1E 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2617 00000E20 750E                <1> 	jne	short TEST_E1
  2618 00000E22 800D[86620000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2619 00000E29 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2620                              <1> 	; 05/12/2021
  2621 00000E2B E9DA010000          <1> 	jmp	K26A	
  2622                              <1> TEST_E1:	
  2623 00000E30 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2624 00000E32 750C                <1> 	jne	short NOT_HC
  2625 00000E34 800D[86620000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2626 00000E3B E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2627                              <1> 	;
  2628                              <1> NOT_HC:
  2629 00000E40 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2630 00000E42 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2631 00000E45 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2632                              <1> 	;
  2633 00000E47 BF[6E610000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2634 00000E4C AE                  <1> 	scasb
  2635                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2636                              <1> 	; 05/12/2021
  2637 00000E4D 7458                <1> 	je	short K16B
  2638 00000E4F AE                  <1> 	scasb
  2639 00000E50 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2640 00000E52 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2641                              <1> 	; 05/12/2021
  2642                              <1> 	;jmp	K26
  2643                              <1> 	;
  2644                              <1> NOT_LC_E0:
  2645 00000E54 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2646 00000E57 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2647 00000E59 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2648 00000E5E BF[6C610000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2649 00000E63 F2AE                <1> 	repne	scasb			; CHECK IT
  2650 00000E65 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2651                              <1> 	; 05/12/2021
  2652                              <1> 	;je	K26A			
  2653                              <1> 	;
  2654 00000E67 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2655 00000E69 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2656                              <1> 	; 05/12/2021
  2657                              <1> 	;jne	K26
  2658 00000E6B F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2659 00000E6E 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2660                              <1> 	; 05/12/2021
  2661                              <1> 	;jnz	K26
  2662                              <1>         ; 20/02/2015 
  2663 00000E70 F605[84620000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2664 00000E77 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2665                              <1> 	; 05/12/2021
  2666                              <1> 	;jnz	K26
  2667 00000E79 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2668                              <1> 	;
  2669                              <1> 	;-----	TEST FOR SYSTEM KEY
  2670                              <1> T_SYS_KEY:
  2671 00000E7E 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2672 00000E80 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2673                              <1> 	;
  2674 00000E82 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2675 00000E85 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2676                              <1> 	;
  2677 00000E87 F605[84620000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2678 00000E8E 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2679                              <1> 	;jnz	K26			
  2680                              <1> 	;
  2681 00000E90 800D[84620000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2682 00000E97 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2683 00000E99 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2684                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2685 00000E9B B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2686 00000E9D E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2687                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2688                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2689                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2690                              <1> 	;INT	15H			; USER INTERRUPT	
  2691 00000EA2 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2692                              <1> 	;
  2693 00000EA7 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2694                              <1> 	;
  2695                              <1> K16C:
  2696 00000EAC 8025[84620000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2697 00000EB3 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2698 00000EB5 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2699                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2700                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2701                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2702                              <1> 	;
  2703                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2704                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2705                              <1> 	;INT	15H			; USER INTERRUPT
  2706                              <1> 	;JMP	K27A			; IGNORE SYSTEM KEY				
  2707                              <1> 	;
  2708 00000EB7 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2709                              <1> 	;
  2710                              <1> 	;-----	TEST FOR SHIFT KEYS
  2711                              <1> K16A:
  2712 00000EBC 8A1D[83620000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2713 00000EC2 BF[68610000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2714 00000EC7 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2715 00000ECC F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2716 00000ECE 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2717                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2718                              <1> 	; 05/12/2021
  2719 00000ED0 7405                <1> 	je	short K17
  2720 00000ED2 E914010000          <1> 	jmp	K25
  2721                              <1> 	;
  2722                              <1> 	;------	SHIFT KEY FOUND
  2723                              <1> K17:
  2724 00000ED7 81EF[69610000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2725 00000EDD 8AA7[70610000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2726 00000EE3 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2727 00000EE5 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2728                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2729                              <1> 	; 05/12/2021
  2730 00000EE7 7405                <1> 	jz	short K17C
  2731 00000EE9 E999000000          <1> 	jmp	K23
  2732                              <1> 	;
  2733                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2734                              <1> K17C:
  2735 00000EEE 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2736 00000EF1 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2737                              <1> 	;
  2738                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2739 00000EF3 0825[83620000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2740 00000EF9 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2741 00000EFB 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2742                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2743                              <1> 	; 05/12/2021
  2744 00000EFD E901010000          <1> 	jmp	K26
  2745                              <1> K17D:
  2746 00000F02 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2747 00000F05 740B                <1> 	jz 	short K17E		; NO, JUMP
  2748 00000F07 0825[86620000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2749 00000F0D E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2750                              <1> K17E:
  2751 00000F12 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2752 00000F14 0825[84620000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2753 00000F1A E9E4000000          <1> 	jmp	K26
  2754                              <1> 	;
  2755                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2756                              <1> K18:					; SHIFT-TOGGLE
  2757 00000F1F F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2758 00000F22 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2759                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2760                              <1> 	; 05/12/2021
  2761 00000F24 E9C2000000          <1> 	jmp	K25
  2762                              <1> K18A:
  2763 00000F29 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2764 00000F2B 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2765 00000F2D F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2766 00000F30 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2767                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2768                              <1> 	; 05/12/2021
  2769 00000F32 E9B4000000          <1> 	jmp	K25
  2770                              <1> K18B:
  2771 00000F37 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2772 00000F3A 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2773                              <1> K19:	
  2774 00000F3C F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2775 00000F3F 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2776 00000F41 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2777 00000F44 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2778                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2779 00000F46 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2780 00000F48 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2781                              <1> K21:					; MIGHT BE NUMERIC
  2782 00000F4D F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2783 00000F50 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2784                              <1> 	;
  2785                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2786 00000F52 8425[84620000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2787                              <1> 	;jnz	K26
  2788                              <1> 	; 05/12/2021
  2789 00000F58 7405                <1> 	jz	short K22A
  2790 00000F5A E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2791                              <1> K22A:
  2792 00000F5F 0825[84620000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2793 00000F65 3025[83620000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2794                              <1> 	;
  2795                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2796 00000F6B F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2797 00000F6E 7407                <1> 	jz	short K22B		; GO IF NOT
  2798                              <1> 	;
  2799                              <1> 	; 05/12/2021
  2800                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2801 00000F70 50                  <1> 	push	eax
  2802 00000F71 E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2803                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2804 00000F76 58                  <1> 	pop	eax
  2805                              <1> K22B:
  2806 00000F77 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2807                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2808                              <1> 	; 05/12/2021
  2809 00000F79 7405                <1> 	je	short K22C
  2810 00000F7B E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2811                              <1> K22C:
  2812 00000F80 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2813 00000F82 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2814                              <1> 	;
  2815                              <1> 	;-----	BREAK SHIFT FOUND
  2816                              <1> K23:					; BREAK-SHIFT-FOUND
  2817 00000F87 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2818 00000F8A F6D4                <1> 	not	ah			; INVERT MASK
  2819 00000F8C 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2820 00000F8E 2025[83620000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2821 00000F94 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2822 00000F97 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2823                              <1> 	;
  2824 00000F99 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2825 00000F9C 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2826 00000F9E 2025[86620000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2827 00000FA4 EB08                <1> 	jmp	short K23B		; CONTINUE
  2828                              <1> K23A:
  2829 00000FA6 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2830 00000FA8 2025[84620000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2831                              <1> K23B:
  2832 00000FAE 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2833 00000FB0 A0[86620000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2834 00000FB5 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2835 00000FB7 0A05[84620000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2836 00000FBD D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2837 00000FBF 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2838 00000FC1 0805[83620000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2839 00000FC7 88E0                <1> 	mov	al, ah
  2840                              <1> K23D:
  2841 00000FC9 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2842 00000FCB 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2843                              <1> 	;	
  2844                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2845 00000FCD A0[87620000]        <1> 	mov	al, [ALT_INPUT]
  2846 00000FD2 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2847 00000FD4 8825[87620000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2848 00000FDA 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2849 00000FDC 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2850 00000FDE E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2851                              <1> 	;
  2852                              <1> K24:					; BREAK-TOGGLE
  2853 00000FE3 2025[84620000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2854 00000FE9 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2855                              <1> 	;
  2856                              <1> 	;-----	TEST FOR HOLD STATE
  2857                              <1> 					; AL, AH = SCAN CODE
  2858                              <1> K25:					; NO-SHIFT-FOUND
  2859 00000FEB 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2860 00000FED 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2861 00000FEF F605[84620000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2862 00000FF6 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2863 00000FF8 3C45                <1> 	cmp	al, NUM_KEY
  2864 00000FFA 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2865 00000FFC 8025[84620000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2866                              <1> 	;
  2867                              <1> K26:
  2868 00001003 8025[86620000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2869                              <1> K26A:					; INTERRUPT-RETURN
  2870 0000100A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2871 0000100B B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2872 0000100D E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2873                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2874 0000100F B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2875 00001011 E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2876                              <1> K27A:
  2877 00001016 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2878 00001017 07                  <1> 	pop	es			; RESTORE REGISTERS
  2879 00001018 1F                  <1> 	pop	ds
  2880 00001019 5F                  <1> 	pop	edi
  2881 0000101A 5E                  <1> 	pop	esi
  2882 0000101B 5A                  <1> 	pop	edx
  2883 0000101C 59                  <1> 	pop	ecx
  2884 0000101D 5B                  <1> 	pop	ebx
  2885 0000101E 58                  <1> 	pop	eax
  2886                              <1> 	;pop	ebp
  2887 0000101F CF                  <1> 	iret				; RETURN
  2888                              <1> 
  2889                              <1> 	;-----	NOT IN	HOLD STATE
  2890                              <1> K28:					; NO-HOLD-STATE
  2891 00001020 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2892 00001022 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2893                              <1> 	;
  2894 00001024 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2895 00001027 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2896                              <1>         ; 05/12/2021
  2897                              <1> 	;jz      K38
  2898                              <1> 	;
  2899 00001029 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2900 0000102C 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2901                              <1> 	; 28/02/2015
  2902 0000102E F605[84620000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2903 00001035 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2904                              <1> 	; 05/12/2021
  2905                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2906                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2907 00001037 E9CD000000          <1> K28A:	jmp	K38
  2908                              <1> 	;
  2909                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2910                              <1> K29:					; TEST-RESET
  2911 0000103C F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2912 0000103F 740B                <1> 	jz	short K31		; NO_RESET
  2913 00001041 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2914 00001043 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2915                              <1> 	;
  2916                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2917                              <1>  	; 26/08/2014
  2918                              <1> cpu_reset:
  2919                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2920                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2921 00001045 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2922 00001047 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2923                              <1> khere:
  2924 00001049 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2925 0000104A EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2926                              <1> 
  2927                              <1> 	;
  2928                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2929                              <1> K31:					; NO-RESET
  2930 0000104C 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2931 0000104E 7507                <1> 	jne	short K311		; NOT THERE
  2932 00001050 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2933 00001052 E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2934                              <1> K311:
  2935 00001057 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2936 00001059 7509                <1> 	jne	short K312		; NOT THERE
  2937 0000105B 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2938 0000105F E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2939                              <1> K312:
  2940 00001064 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2941 00001066 7471                <1>         je	short K37B              ; GO PROCESS
  2942 00001068 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2943 0000106A 746D                <1>         je	short K37B              ; GO PROCESS
  2944                              <1> 	;
  2945                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2946                              <1> K32:					; ALT-KEY-PAD
  2947 0000106C BF[44610000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2948 00001071 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2949 00001076 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2950 00001078 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2951 0000107A F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2952                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2953                              <1> 	; 05/12/2021
  2954 0000107D 751C                <1> 	jnz	short K32B
  2955 0000107F 81EF[45610000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2956 00001085 A0[87620000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2957 0000108A B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2958 0000108C F6E4                <1> 	mul	ah
  2959 0000108E 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2960 00001091 A2[87620000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2961                              <1> K32A:
  2962 00001096 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2963                              <1> K32B:
  2964                              <1> 	; 05/12/2021
  2965 0000109B EB66                <1> 	jmp	K37C
  2966                              <1> 	;
  2967                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2968                              <1> K33:					; NO-ALT-KEYPAD
  2969 0000109D C605[87620000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2970 000010A4 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2971 000010A9 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2972 000010AB 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2973                              <1> 	;
  2974                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2975                              <1> K34:					; ALT-TOP-ROW
  2976 000010AD 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2977 000010AF 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2978 000010B1 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2979 000010B3 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2980 000010B5 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2981 000010B8 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2982                              <1> 	;
  2983                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2984                              <1> K35:					; ALT-FUNCTION
  2985 000010BA 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2986 000010BC 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2987 000010BE 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2988 000010C0 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2989 000010C2 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2990 000010C5 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2991                              <1> K35A:
  2992 000010C7 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2993 000010CA 7425                <1> 	jz	short K37		; NO, JUMP
  2994 000010CC 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2995 000010CE 7510                <1>         jne     short K35B              ; NOT THERE
  2996 000010D0 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2997 000010D4 E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  2998                              <1> K37B:
  2999 000010D9 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3000 000010DB E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3001                              <1> K35B:
  3002 000010E0 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3003 000010E2 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3004 000010E4 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3005 000010E6 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3006                              <1>         ; 05/12/2021
  3007                              <1> 	;jne	K26
  3008 000010E8 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3009 000010EC E998010000          <1> 	jmp	K57			; BUFFER FILL
  3010                              <1> K37:
  3011 000010F1 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3012 000010F3 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3013 000010F5 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3014 000010F7 779D                <1>         ja	short K32A		; IF SO, IGNORE
  3015                              <1> 	; 11/06/2022
  3016                              <1> 	;ja      K26
  3017 000010F9 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3018                              <1> K37A:
  3019 000010FC B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3020 000010FE E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3021                              <1> K37C:
  3022 00001103 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3023 00001105 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3024 00001107 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3025                              <1> 	;
  3026                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3027                              <1> K38:					; NOT-ALT-SHIFT
  3028                              <1> 					; BL STILL HAS SHIFT FLAGS
  3029 00001109 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3030 0000110C 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3031                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3032                              <1> 	; 05/12/2021
  3033 0000110E E9AB000000          <1> 	jmp	K44
  3034                              <1> 	;
  3035                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3036                              <1> 	;-----	TEST FOR BREAK
  3037                              <1> K38A:
  3038 00001113 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3039 00001115 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3040 00001117 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3041 0000111A 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3042 0000111C F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3043 0000111F 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3044                              <1> K38B:
  3045 00001121 8B1D[90620000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3046 00001127 891D[94620000]      <1> 	mov	[BUFFER_TAIL], ebx
  3047 0000112D C605[82620000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3048                              <1> 	;
  3049                              <1> 	;-----	ENABLE KEYBOARD
  3050 00001134 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3051 00001136 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3052                              <1> 	;
  3053                              <1> 	; CTRL+BREAK code here !!!
  3054                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3055                              <1> 	; 17/10/2015	
  3056 0000113B E8AE190000          <1> 	call	ctrlbrk ; control+break subroutine
  3057                              <1> 	;
  3058                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3059                              <1> 	; 05/12/2021
  3060 00001140 29C0                <1> 	sub	eax, eax
  3061 00001142 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3062                              <1> 	;
  3063                              <1> 	;-----	TEST FOR PAUSE
  3064                              <1> K39:					; NO_BREAK
  3065 00001147 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3066 0000114A 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3067 0000114C 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3068 0000114E 7533                <1> 	jne	short K41		; NO-PAUSE
  3069                              <1> K39P:
  3070 00001150 800D[84620000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3071                              <1> 	;
  3072                              <1> 	;-----	ENABLE KEYBOARD
  3073 00001157 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3074 00001159 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3075                              <1> K39A:
  3076 0000115E B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3077 00001160 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3078                              <1> 	;
  3079                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3080 00001162 803D[80620000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3081 00001169 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3082 0000116B 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3083 0000116F A0[81620000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3084 00001174 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3085                              <1> 	;
  3086                              <1> K40:					; PAUSE-LOOP
  3087 00001175 F605[84620000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3088 0000117C 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3089                              <1> 	;
  3090 0000117E E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3091                              <1>         ;
  3092                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3093                              <1> K41:					; NO-PAUSE
  3094 00001183 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3095 00001185 7513                <1> 	jne	short K42		; NOT-KEY-55
  3096 00001187 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3097 0000118A 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3098 0000118C F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3099 0000118F 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3100                              <1> K41A:	
  3101 00001191 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3102 00001195 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3103                              <1> 	;
  3104                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3105                              <1> K42:					; NOT-KEY-55
  3106 0000119A 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3107 0000119C 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3108 0000119E 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3109 000011A0 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3110 000011A2 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3111 000011A5 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3112 000011A7 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3113 000011AB E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3114                              <1> K42A:
  3115                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3116 000011B0 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3117                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3118                              <1> 	;;jb	K56 ; 20/02/2015
  3119                              <1> 	;;jmp	K64 ; 20/02/2015
  3120                              <1> K42B:
  3121 000011B2 BB[78610000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3122                              <1> 	;;jmp	K64
  3123                              <1> 	;jb	K56 ;; 20/02/2015	
  3124                              <1> 	; 05/12/2021
  3125 000011B7 7267                <1> 	jb	short K45F
  3126 000011B9 E9B9000000          <1> 	jmp	K64	
  3127                              <1>         ;
  3128                              <1> 	;-----	NOT IN CONTROL SHIFT
  3129                              <1> K44:					; NOT-CTL-SHIFT
  3130 000011BE 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3131 000011C0 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3132 000011C2 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3133 000011C5 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3134 000011C7 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3135 000011CA 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3136 000011CC EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3137                              <1> K44A:
  3138 000011CE F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3139 000011D1 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3140                              <1> 	;
  3141                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3142                              <1> K44B:
  3143 000011D3 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3144 000011D5 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3145 000011DA B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3146 000011DC E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3147                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3148                              <1> 	;PUSH 	BP			; SAVE POINTER
  3149                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3150                              <1> 	;POP	BP			; RESTORE POINTER
  3151 000011DE 8025[86620000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3152 000011E5 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3153                              <1> 	;
  3154                              <1> 	;-----	HANDLE IN-CORE KEYS
  3155                              <1> K45:					; NOT-PRINT-SCREEN
  3156 000011EA 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3157 000011EC 7734                <1> 	ja	short K46		; JUMP IF NOT
  3158 000011EE 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3159 000011F0 7505                <1> 	jne	short K45A		; NO, JUMP
  3160 000011F2 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3161 000011F5 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3162                              <1> K45A:
  3163 000011F7 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3164 000011FC BF[4E610000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3165 00001201 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3166                              <1> 		; 20/02/2015
  3167 00001203 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3168                              <1> 	;
  3169 00001205 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3170 00001208 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3171                              <1> K45B:
  3172 0000120A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3173 0000120D 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3174                              <1> 					; NO, LOWERCASE
  3175                              <1> K45C:
  3176 0000120F BB[D0610000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3177 00001214 EB51                <1> 	jmp	short K56	
  3178                              <1> K45D:					; ALMOST-CAPS-STATE
  3179 00001216 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3180 00001219 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3181                              <1> K45E:
  3182 0000121B BB[28620000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3183 00001220 EB45                <1> K45F:	jmp	short K56
  3184                              <1> 	;
  3185                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3186                              <1> K46:					; NOT IN-CORE AREA
  3187 00001222 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3188                              <1> 	;ja	short K47		; JUMP IF NOT
  3189                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3190 00001224 7635                <1> 	jna	short K53		
  3191                              <1> 	;
  3192                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3193                              <1> K47:					; NOT F1 - F10
  3194 00001226 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3195 00001228 772D                <1> 	ja	short K52		; JUMP IF NOT
  3196                              <1> 	;
  3197                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3198                              <1> K48:
  3199 0000122A 3C4A                <1> 	cmp	al, 74			; SPECIAL CASE FOR MINUS
  3200 0000122C 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3201 0000122E 3C4E                <1> 	cmp	al, 78			; SPECIAL CASE FOR PLUS
  3202 00001230 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3203 00001232 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3204 00001235 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3205                              <1> 	;		
  3206 00001237 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3207 0000123A 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3208 0000123C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3209                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3210 0000123F 75DA                <1> 	jnz	short K45E
  3211                              <1> 	;
  3212                              <1> 	;-----	BASE CASE FOR KEYPAD
  3213                              <1> K49:					
  3214 00001241 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3215 00001243 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3216 00001245 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3217 00001247 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3218                              <1> K49A:
  3219 00001249 BB[D0610000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3220 0000124E EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3221                              <1> 	;
  3222                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3223                              <1> K50:					; ALMOST-NUM-STATE
  3224 00001250 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3225 00001253 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3226 00001255 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3227                              <1> 	;
  3228                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3229                              <1> K52:					; NOT A NUMPAD KEY
  3230 00001257 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3231                              <1> 	;jne	short K53		; JUMP IF NOT
  3232                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3233 00001259 74AF                <1> 	je	short K45B		
  3234                              <1> 	;
  3235                              <1> 	;-----	MUST BE F11 OR F12 
  3236                              <1> K53:					; F1 - F10 COME HERE, TOO
  3237 0000125B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3238 0000125E 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3239                              <1> 		; 20/02/2015 
  3240 00001260 BB[28620000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3241 00001265 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3242                              <1> 	;
  3243                              <1> 	;-----	TRANSLATE THE CHARACTER
  3244                              <1> K56:					; TRANSLATE-CHAR
  3245 00001267 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3246 00001269 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3247 0000126A F605[86620000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3248 00001271 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3249 00001273 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3250 00001275 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3251                              <1> 	;
  3252                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3253                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3254 00001277 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3255 00001279 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3256 0000127A 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3257 0000127C B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3258 0000127E F605[86620000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3259 00001285 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3260 00001287 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3261                              <1> 	;
  3262                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3263                              <1> K57:					; BUFFER_FILL
  3264 00001289 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3265 0000128B 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3266                              <1> 	; 05/12/2021
  3267                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3268 0000128D 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3269                              <1> 	; 05/12/2021
  3270 00001290 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3271                              <1> 	;je	K26			; INTERRUPT_RETURN
  3272                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3273 00001292 E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3274                              <1> K61:					; NOT-CAPS-STATE
  3275 00001297 8B1D[94620000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3276 0000129D 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3277 0000129F E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3278 000012A4 3B1D[90620000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3279 000012AA 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3280 000012AC 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3281 000012AF 891D[94620000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3282 000012B5 E949FDFFFF          <1> 	jmp	K26
  3283                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3284                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3285                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3286                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3287                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3288                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3289                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3290                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3291                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3292                              <1> 	;;jmp   K27                    
  3293                              <1> 	;
  3294                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3295                              <1> K62:
  3296 000012BA B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3297 000012BC E620                <1> 	out	INTA00, al
  3298 000012BE 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3299 000012C2 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3300 000012C4 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3301 000012C9 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3302                              <1> 
  3303                              <1> SHIP_IT:
  3304                              <1> 	;---------------------------------------------------------------------------------
  3305                              <1> 	; SHIP_IT
  3306                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3307                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3308                              <1> 	;---------------------------------------------------------------------------------
  3309                              <1> 	;
  3310                              <1> 	;push	ax			; SAVE DATA TO SEND
  3311                              <1> 	; 05/12/2021
  3312 000012CE 50                  <1> 	push	eax
  3313                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3314 000012CF FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3315                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3316 000012D0 B900000100          <1> 	mov	ecx, 10000h			
  3317                              <1> S10:
  3318 000012D5 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3319 000012D7 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3320 000012D9 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3321                              <1> 
  3322                              <1> 	;pop	ax			; GET DATA TO SEND
  3323                              <1> 	; 05/12/2021
  3324 000012DB 58                  <1> 	pop	eax
  3325 000012DC E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3326 000012DE FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3327 000012DF C3                  <1> 	retn				; RETURN TO CALLER
  3328                              <1> 
  3329                              <1> SND_DATA:
  3330                              <1> 	; ---------------------------------------------------------------------------------
  3331                              <1> 	; SND_DATA
  3332                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3333                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3334                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3335                              <1> 	; ---------------------------------------------------------------------------------
  3336                              <1> 	;
  3337                              <1> 	;push	ax			; SAVE REGISTERS
  3338                              <1> 	;push	bx
  3339                              <1> 	; 05/12/2021
  3340 000012E0 50                  <1> 	push	eax
  3341 000012E1 53                  <1> 	push	ebx
  3342 000012E2 51                  <1> 	push	ecx
  3343 000012E3 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3344 000012E5 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3345                              <1> SD0:
  3346 000012E7 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3347 000012E8 8025[85620000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3348                              <1> 	;
  3349                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3350 000012EF B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3351                              <1> SD5:
  3352 000012F4 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3353 000012F6 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3354 000012F8 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3355                              <1> 	;
  3356 000012FA 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3357 000012FC E660                <1> 	out	PORT_A, al		; SEND BYTE
  3358 000012FE FB                  <1> 	sti				; ENABLE INTERRUPTS
  3359                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3360 000012FF B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3361                              <1> SD1:
  3362 00001304 F605[85620000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3363 0000130B 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3364 0000130D E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3365                              <1> SD2:
  3366 0000130F FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3367 00001311 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3368 00001313 800D[85620000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3369 0000131A EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3370                              <1> SD3:
  3371 0000131C F605[85620000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3372 00001323 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3373                              <1> SD4:	
  3374 00001325 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3375                              <1> 	;pop	bx
  3376                              <1> 	;pop	ax
  3377                              <1> 	; 05/12/2021
  3378 00001326 5B                  <1> 	pop	ebx
  3379 00001327 58                  <1> 	pop	eax
  3380 00001328 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3381                              <1> 
  3382                              <1> SND_LED:
  3383                              <1> 	; ---------------------------------------------------------------------------------
  3384                              <1> 	; SND_LED
  3385                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3386                              <1> 	;
  3387                              <1> 	;----------------------------------------------------------------------------------
  3388                              <1> 	;
  3389 00001329 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3390 0000132A F605[85620000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3391 00001331 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3392                              <1> 	;
  3393 00001333 800D[85620000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3394 0000133A B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3395 0000133C E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3396 0000133E EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3397                              <1> SND_LED1:
  3398 00001340 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3399 00001341 F605[85620000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3400 00001348 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3401                              <1> 	;
  3402 0000134A 800D[85620000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3403                              <1> SL0:
  3404 00001351 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3405 00001353 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3406 00001358 FA                  <1> 	cli
  3407 00001359 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3408 0000135E 8025[85620000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3409 00001365 0805[85620000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3410 0000136B F605[85620000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3411 00001372 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3412                              <1> 	;
  3413 00001374 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3414 00001379 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3415 0000137A F605[85620000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3416 00001381 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3417                              <1> SL2:
  3418 00001383 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3419 00001385 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3420 0000138A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3421                              <1> SL3:
  3422 0000138B 8025[85620000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3423                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3424 00001392 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3425 00001393 C3                  <1> 	retn				; RETURN TO CALLER
  3426                              <1> 
  3427                              <1> MAKE_LED:
  3428                              <1> 	;---------------------------------------------------------------------------------
  3429                              <1> 	; MAKE_LED
  3430                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3431                              <1> 	;	THE MODE INDICATORS.
  3432                              <1> 	;---------------------------------------------------------------------------------
  3433                              <1> 	;
  3434                              <1> 	;push 	cx			; SAVE CX
  3435 00001394 A0[83620000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3436 00001399 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3437                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3438                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3439 0000139B C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3440 0000139E 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3441                              <1> 	;pop	cx
  3442 000013A0 C3                  <1> 	retn				; RETURN TO CALLER
  3443                              <1> 
  3444                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3445                              <1> 
  3446                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1865                                  
  1866                                  %include 'video.s' ; 07/03/2015
  1867                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1868                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1869                              <1> ; ****************************************************************************
  1870                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - VIDEO.INC
  1871                              <1> ; Last Modification: 14/06/2022
  1872                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1873                              <1> ;
  1874                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1875                              <1> 
  1876                              <1> ; 27/02/2022
  1877                              <1> ; 23/02/2022
  1878                              <1> ; 21/02/2022 (Retro UNIX 386 v1.2)
  1879                              <1> ; 07/02/2022 (Retro UNIX 386 V1&v1.1)
  1880                              <1> ; 02/02/2022 (simplified scroll up)
  1881                              <1> ; 16/01/2016
  1882                              <1> ; 30/06/2015
  1883                              <1> ; 27/06/2015
  1884                              <1> ; 11/03/2015
  1885                              <1> ; 02/09/2014
  1886                              <1> ; 30/08/2014
  1887                              <1> ; VIDEO FUNCTIONS
  1888                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1889                              <1> 
  1890                              <1> write_tty:
  1891                              <1> 	; 02/02/2022
  1892                              <1> 	; 13/08/2015
  1893                              <1> 	; 02/09/2014
  1894                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1895                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1896                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1897                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1898                              <1> 	;
  1899                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1900                              <1> 	;	   AL = Character to be written
  1901                              <1> 	;	   EBX = Video Page (0 to 7)
  1902                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1903                              <1> 
  1904                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1905                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1906                              <1> 
  1907                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1908                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1909                              <1> ;
  1910                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1911                              <1> ;
  1912                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1913                              <1> ;										:
  1914                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1915                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1916                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1917                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1918                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1919                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1920                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1921                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1922                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1923                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1924                              <1> ;   THE 0 COLOR IS USED.							:
  1925                              <1> ;   ENTRY --									:
  1926                              <1> ;     (AH) = CURRENT CRT MODE							:
  1927                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1928                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1929                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1930                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1931                              <1> ;   EXIT -- 									:
  1932                              <1> ;     ALL REGISTERS SAVED							:
  1933                              <1> ;--------------------------------------------------------------------------------
  1934                              <1> 
  1935 000013A1 FA                  <1> 	cli
  1936                              <1> 	;
  1937                              <1> 	; READ CURSOR (04/12/2013)
  1938                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1939 000013A2 08FF                <1> 	or	bh, bh
  1940                              <1> 	;jnz	beeper
  1941                              <1> 	; 02/02/2022
  1942 000013A4 7405                <1> 	jz	short u14
  1943 000013A6 E992000000          <1> 	jmp	beeper
  1944                              <1> u14:
  1945                              <1> 	; 02/02/2022
  1946                              <1> 	;; 01/09/2014
  1947                              <1> 	;cmp	byte [CRT_MODE], 3
  1948                              <1> 	;je	short m3
  1949                              <1> 	;;
  1950                              <1> 	;call	set_mode
  1951                              <1> m3:
  1952 000013AB 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1953                              <1> 	;shl	si, 1
  1954                              <1> 	; 02/02/2022
  1955 000013AD D1E6                <1> 	shl	esi, 1
  1956 000013AF 81C6[46680000]      <1> 	add	esi, cursor_posn
  1957 000013B5 668B16              <1> 	mov	dx, [esi]
  1958                              <1> 	;
  1959                              <1> 	; dx now has the current cursor position
  1960                              <1> 	;
  1961 000013B8 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1962 000013BA 7647                <1> 	jbe	short u8
  1963                              <1> 	;
  1964                              <1> 	; write the char to the screen
  1965                              <1> u0:	
  1966                              <1> 	; ah = attribute/color
  1967                              <1> 	; al = character
  1968                              <1> 	; bl = video page number (0 to 7)
  1969                              <1> 	; bh = 0
  1970                              <1> 	;
  1971 000013BC E8D2010000          <1> 	call	write_c_current
  1972                              <1> 	;
  1973                              <1> 	; position the cursor for next char
  1974 000013C1 FEC2                <1> 	inc	dl		; next column
  1975                              <1> 	;cmp	dl, [CRT_COLS]
  1976 000013C3 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1977                              <1>         ;jne	set_cpos
  1978                              <1> 	; 02/02/2022
  1979 000013C6 7405                <1> 	je	short u13
  1980 000013C8 E9DE000000          <1> 	jmp	set_cpos
  1981                              <1> u13:
  1982 000013CD B200                <1> 	mov	dl, 0		; column = 0
  1983                              <1> u10:				; (line feed found)
  1984 000013CF 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1985 000013D2 7228                <1> 	jb 	short u6
  1986                              <1> 	;
  1987                              <1> 	; scroll required
  1988                              <1> u1:	
  1989                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1990 000013D4 E8D2000000          <1> 	call	set_cpos
  1991                              <1> 	;
  1992                              <1> 	; determine value to fill with during scroll
  1993                              <1> u2:
  1994                              <1> 	; READ_AC_CURRENT		:
  1995                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1996                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1997                              <1> 	;
  1998                              <1> 	; INPUT				
  1999                              <1> 	;	(AH) = CURRENT CRT MODE
  2000                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2001                              <1> 	;	(DS) = DATA SEGMENT
  2002                              <1> 	;	(ES) = REGEN SEGMENT
  2003                              <1> 	; OUTPUT			
  2004                              <1> 	;	(AL) = CHARACTER READ
  2005                              <1> 	;	(AH) = ATTRIBUTE READ
  2006                              <1> 	;
  2007                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2008                              <1> 	;
  2009                              <1> 	; bl = video page number
  2010                              <1> 	;
  2011 000013D9 E829010000          <1> 	call	find_position	; get regen location and port address
  2012                              <1> 	; dx = status port
  2013                              <1> 	; esi = cursor location/address
  2014                              <1> p11:
  2015 000013DE FB                  <1> 	sti			; enable interrupts
  2016 000013DF 90                  <1> 	nop			; allow for small interupts window
  2017 000013E0 FA                  <1> 	cli			; blocks interrupts for single loop
  2018 000013E1 EC                  <1> 	in	al, dx		; get status from adapter
  2019 000013E2 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2020 000013E4 75F8                <1> 	jnz	short p11	; wait until it is
  2021                              <1> p12:				; now wait for either retrace high
  2022 000013E6 EC                  <1> 	in	al, dx		; get status
  2023 000013E7 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2024 000013E9 74FB                <1> 	jz	short p12	; wait until either is active	
  2025                              <1> p13:
  2026 000013EB 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2027 000013F1 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2028                              <1> 	;
  2029                              <1> 	; al = character, ah = attribute
  2030                              <1> 	;
  2031 000013F4 FB                  <1> 	sti
  2032                              <1> 	; bl = video page number 	
  2033                              <1> u3:
  2034                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2035                              <1> 	;;sub	cx, cx		; upper left corner
  2036                              <1> 	;;mov	dh, 25-1 	; lower right row
  2037                              <1> 	;;;mov	dl, [CRT_COLS]
  2038                              <1> 	;mov	dl, 80		; lower right column	
  2039                              <1> 	;;dec	dl
  2040                              <1> 	;;mov	dl, 79
  2041                              <1> 
  2042                              <1> 	;;call	scroll_up	; 04/12/2013
  2043                              <1> 	;;; 11/03/2015
  2044                              <1> 	; 02/09/2014
  2045                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2046                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2047                              <1> 	; 11/03/2015
  2048                              <1> 	;sub	cx, cx
  2049                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2050                              <1> 	;
  2051                              <1> 	; 02/02/2022 (simplied scroll up)
  2052                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2053                              <1> 	;
  2054 000013F5 B001                <1> 	mov	al, 1		; scroll 1 line up
  2055                              <1> 		; ah = attribute
  2056 000013F7 E935010000          <1> 	jmp	scroll_up
  2057                              <1> ;u4:
  2058                              <1> 	;;int	10h		; video-call return
  2059                              <1> 				; scroll up the screen
  2060                              <1> 				; tty return
  2061                              <1> ;u5:
  2062                              <1> 	;retn			; return to the caller
  2063                              <1> 
  2064                              <1> u6:				; set-cursor-inc
  2065 000013FC FEC6                <1> 	inc	dh		; next row
  2066                              <1> 				; set cursor
  2067                              <1> ;u7:					
  2068                              <1> 	;;mov	ah, 02h
  2069                              <1> 	;;jmp	short u4 	; establish the new cursor
  2070                              <1> 	;call	set_cpos
  2071                              <1> 	;jmp 	short u5
  2072 000013FE E9A8000000          <1> 	jmp     set_cpos
  2073                              <1> 
  2074                              <1> 	; check for control characters
  2075                              <1> u8:
  2076 00001403 7434                <1> 	je	short u9
  2077 00001405 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2078 00001407 74C6                <1> 	je	short u10
  2079 00001409 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2080 0000140B 7430                <1> 	je	short u11
  2081 0000140D 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2082                              <1> 	;jne	short u0
  2083 0000140F 7420                <1> 	je	short bs	; 12/12/2013
  2084                              <1> 	; 12/12/2013 (tab stop)
  2085 00001411 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2086 00001413 75A7                <1> 	jne	short u0
  2087 00001415 88D0                <1> 	mov	al, dl
  2088 00001417 6698                <1> 	cbw
  2089 00001419 B108                <1> 	mov	cl, 8
  2090 0000141B F6F1                <1> 	div	cl
  2091 0000141D 28E1                <1> 	sub	cl, ah
  2092                              <1> ts:
  2093                              <1> 	; 02/09/2014
  2094                              <1> 	; 01/09/2014
  2095 0000141F B020                <1> 	mov	al, 20h
  2096                              <1> tsloop:
  2097                              <1> 	;push	cx
  2098                              <1> 	;push	ax
  2099                              <1> 	; 02/02/2022
  2100 00001421 51                  <1> 	push	ecx
  2101 00001422 50                  <1> 	push	eax
  2102 00001423 30FF                <1> 	xor 	bh, bh
  2103                              <1> 	;mov	bl, [active_page]
  2104 00001425 E881FFFFFF          <1> 	call	m3
  2105                              <1> 	; 02/02/2022
  2106 0000142A 58                  <1> 	pop	eax
  2107 0000142B 59                  <1>  	pop	ecx
  2108                              <1> 	;pop	ax  ; ah = attribute/color
  2109                              <1> 	;pop	cx
  2110 0000142C FEC9                <1> 	dec	cl
  2111 0000142E 75F1                <1> 	jnz	short tsloop
  2112 00001430 C3                  <1> 	retn
  2113                              <1> bs:	
  2114                              <1> 	; back space found
  2115 00001431 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2116                              <1> 	;je	short u7 	; set_cursor
  2117 00001433 7476                <1> 	jz	short set_cpos
  2118                              <1> 	;dec	dx     		; no -- just move it back
  2119                              <1> 	; 02/02/2022
  2120 00001435 FECA                <1> 	dec	dl
  2121                              <1> 	;jmp	short u7
  2122 00001437 EB72                <1> 	jmp	short set_cpos
  2123                              <1> 
  2124                              <1> 	; carriage return found
  2125                              <1> u9:
  2126 00001439 B200                <1> 	mov	dl, 0 		; move to first column
  2127                              <1> 	;jmp	short u7
  2128 0000143B EB6E                <1> 	jmp	short set_cpos
  2129                              <1> 
  2130                              <1> 	; line feed found
  2131                              <1> ;u10:
  2132                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2133                              <1> ;	jne	short u6 	; no, just set the cursor
  2134                              <1> ;       jmp     u1              ; yes, scroll the screen
  2135                              <1> 
  2136                              <1> beeper: 
  2137                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2138                              <1> 	; 18/01/2014
  2139                              <1> 	; 03/12/2013
  2140                              <1> 	; bell found
  2141                              <1> u11:
  2142 0000143D FB                  <1> 	sti
  2143 0000143E 3A1D[56680000]      <1> 	cmp	bl, [active_page]
  2144 00001444 7551                <1> 	jne	short u12	; Do not sound the beep 
  2145                              <1> 				; if it is not written on the active page
  2146 00001446 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2147 0000144A B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2148                              <1> 	;call	beep		; sound the pod bell
  2149                              <1> 	;jmp	short u5 	; tty_return
  2150                              <1> 	;retn
  2151                              <1> 	
  2152                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2153                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2154                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2155                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2156                              <1> 
  2157                              <1> beep:
  2158                              <1> 	; 07/02/2015
  2159                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2160                              <1> 	; 18/01/2014
  2161                              <1> 	; 03/12/2013
  2162                              <1> 	;
  2163                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2164                              <1> 	;
  2165                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2166                              <1> 	;
  2167                              <1> 	; ENTRY:
  2168                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2169                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2170                              <1> 	; EXIT:			:
  2171                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2172                              <1> 
  2173 0000144C 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2174 0000144D FA                  <1> 	cli			; block interrupts during update
  2175 0000144E B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2176 00001450 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2177 00001452 EB00                <1> 	jmp	$+2		; I/O delay
  2178 00001454 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2179 00001456 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2180 00001458 EB00                <1> 	jmp	$+2		; I/O delay
  2181 0000145A 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2182 0000145C E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2183 0000145E E461                <1> 	in	al, PORT_B	; get current setting of port
  2184 00001460 88C4                <1> 	mov	ah, al		; save that setting
  2185 00001462 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2186 00001464 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2187                              <1> 	;popf	; 18/01/2014
  2188 00001466 FB                  <1> 	sti
  2189                              <1> g7:				; 1/64 second per count (bl)
  2190 00001467 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2191 0000146C E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2192 00001471 FECB                <1> 	dec	bl		; (bl) length count expired?
  2193 00001473 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2194                              <1> 	;
  2195                              <1> 	;pushf			; save interrupt status
  2196 00001475 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2197 00001476 E461                <1> 	in	al, PORT_B	; get current port value
  2198                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2199 00001478 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2200 0000147A 20C4                <1>         and	ah, al		; someone turned them off during beep
  2201 0000147C 88E0                <1> 	mov	al, ah		; recover value of port
  2202                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2203 0000147E 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2204 00001480 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2205                              <1> 	;popf			; restore interrupt flag state
  2206 00001482 FB                  <1> 	sti
  2207 00001483 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2208 00001488 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2209                              <1> 	;pushf			; save interrupt status
  2210 0000148D FA                  <1> 	cli			; block interrupts during update
  2211 0000148E E461                <1> 	in	al, PORT_B	; get current port value in case	
  2212 00001490 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2213 00001492 08E0                <1> 	or	al, ah		; recover value of port_b
  2214 00001494 E661                <1> 	out	PORT_B, al	; restore speaker status
  2215 00001496 9D                  <1> 	popf			; restore interrupt flag state
  2216                              <1> u12:	
  2217 00001497 C3                  <1> 	retn
  2218                              <1> 
  2219                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2220                              <1> 
  2221                              <1> WAITF:
  2222                              <1> waitf:
  2223                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2224                              <1> 	; 03/12/2013
  2225                              <1> 	;
  2226                              <1> ;	push	ax		; save work register (ah)	
  2227                              <1> ;waitf1:
  2228                              <1> 				; use timer 1 output bits
  2229                              <1> ;	in	al, PORT_B	; read current counter output status
  2230                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2231                              <1> ;	cmp	al, ah		; did it just change
  2232                              <1> ;	je	short waitf1	; wait for a change in output line
  2233                              <1> ;	;
  2234                              <1> ;	mov	ah, al		; save new lflag state
  2235                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2236                              <1> ;	;
  2237                              <1> ;	pop	ax		; restore (ah)
  2238                              <1> ;	retn			; return (cx)=0
  2239                              <1> 
  2240                              <1> ; 02/02/2022
  2241                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2242                              <1> ; 17/12/2014 (dsectrm2.s)
  2243                              <1> ; WAITF
  2244                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2245                              <1> ;
  2246                              <1> ;---WAITF-----------------------------------------------------------------------
  2247                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2248                              <1> ; ENTRY:
  2249                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2250                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2251                              <1> ; EXIT:
  2252                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2253                              <1> ;	(CX) = 0	
  2254                              <1> ;-------------------------------------------------------------------------------
  2255                              <1> 
  2256                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2257                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2258                              <1> 
  2259                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2260 00001498 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2261                              <1> 	;push	ax
  2262                              <1> 	; 16/12/2014
  2263                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2264 00001499 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2265                              <1> ;17/12/2014	
  2266                              <1> ;WAITF1:
  2267                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2268                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2269                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2270                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2271                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2272                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2273                              <1> 	;
  2274                              <1> 	; 17/12/2014
  2275                              <1> 	;
  2276                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2277                              <1> 	;
  2278                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2279                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2280                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2281                              <1> WR_STATE_0:
  2282 0000149B E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2283 0000149D A810                <1> 	TEST	AL,010H
  2284 0000149F 74FA                <1> 	JZ	SHORT WR_STATE_0
  2285                              <1> WR_STATE_1:
  2286 000014A1 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2287 000014A3 A810                <1> 	TEST	AL,010H
  2288 000014A5 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2289 000014A7 E2F2                <1>         LOOP    WR_STATE_0
  2290                              <1> 	;
  2291                              <1> 	;pop	ax
  2292 000014A9 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2293 000014AA C3                  <1> 	RETn				; (CX) = 0
  2294                              <1> 
  2295                              <1> set_cpos:
  2296                              <1> 	; 14/06/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.2)
  2297                              <1> 	; 27/02/2022
  2298                              <1> 	; 23/02/2022
  2299                              <1> 	; 02/02/2022
  2300                              <1> 	; 27/06/2015
  2301                              <1> 	; 01/09/2014
  2302                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2303                              <1> 	;
  2304                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2305                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2306                              <1> 	;
  2307                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2308                              <1> 	;
  2309                              <1> 	; SET_CPOS
  2310                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2311                              <1> 	;	NEW X-Y VALUES PASSED
  2312                              <1> 	; INPUT
  2313                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2314                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2315                              <1> 	; OUTPUT
  2316                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2317                              <1> 	;
  2318 000014AB 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2319 000014AE D0E0                <1>         shl     al, 1   ; word offset
  2320 000014B0 BE[46680000]        <1> 	mov	esi, cursor_posn
  2321 000014B5 01C6                <1>         add     esi, eax
  2322 000014B7 668916              <1> 	mov	[esi], dx ; save the pointer
  2323 000014BA 381D[56680000]      <1> 	cmp	[active_page], bl
  2324 000014C0 7531                <1> 	jne	short m17
  2325                              <1> 
  2326                              <1> 	; 14/06/2022
  2327                              <1> 	;cli	; 27/02/2022
  2328                              <1> 
  2329                              <1> 	;call	m18	; CURSOR SET
  2330                              <1> ;m17:			; SET_CPOS_RETURN
  2331                              <1> 	; 01/09/2014
  2332                              <1> ;	retn
  2333                              <1> 		; DX = row/column
  2334                              <1> m18:
  2335 000014C2 E832000000          <1> 	call	position ; determine location in regen buffer	
  2336                              <1> 	;mov	cx, [CRT_START]
  2337                              <1> 	; 23/02/2022
  2338 000014C7 0FB70D[44680000]    <1> 	movzx	ecx, word [CRT_START]
  2339 000014CE 01C1                <1> 	add	ecx, eax
  2340                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2341                              <1> 			; to the start address (offset) for this page
  2342                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2343                              <1> 	; 23/02/2022
  2344 000014D0 D1E9                <1> 	shr	ecx, 1
  2345 000014D2 B40E                <1> 	mov	ah, 14	; register number for cursor
  2346                              <1> 	
  2347                              <1> 	; 14/06/2022
  2348                              <1> 	;call	m16	; output value to the 6845
  2349                              <1> 	;sti	; 27/02/2022
  2350                              <1> 	;retn
  2351                              <1> 
  2352                              <1> 	; 14/06/2022
  2353                              <1> 	; 27/02/2022
  2354                              <1> 	; 02/02/2022
  2355                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2356                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2357                              <1> m16:
  2358                              <1> 	; 14/06/2022
  2359 000014D4 FA                  <1> 	cli	; 27/02/2022
  2360                              <1> 	;mov	dx, [addr_6845] ; address register
  2361 000014D5 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2362 000014D9 88E0                <1> 	mov	al, ah	; get value
  2363 000014DB EE                  <1> 	out	dx, al	; register set
  2364                              <1> 	;inc	dx	; data register
  2365                              <1> 	; 02/02/2022
  2366 000014DC FEC2                <1> 	inc	dl
  2367 000014DE EB00                <1> 	jmp	$+2	; i/o delay
  2368 000014E0 88E8                <1> 	mov	al, ch	; data
  2369 000014E2 EE                  <1> 	out	dx, al	
  2370                              <1> 	;dec	dx
  2371                              <1> 	; 02/02/2022	
  2372 000014E3 FECA                <1> 	dec	dl
  2373 000014E5 88E0                <1> 	mov	al, ah
  2374 000014E7 FEC0                <1> 	inc	al	; point to other data register
  2375 000014E9 EE                  <1> 	out	dx, al	; set for second register
  2376                              <1> 	;inc	dx
  2377                              <1> 	; 02/02/2022
  2378 000014EA FEC2                <1> 	inc	dl
  2379 000014EC EB00                <1> 	jmp	$+2	; i/o delay
  2380 000014EE 88C8                <1> 	mov	al, cl	; second data value
  2381 000014F0 EE                  <1> 	out	dx, al
  2382                              <1> 	; 14/06/2022
  2383 000014F1 FB                  <1> 	sti	; 27/02/2022
  2384                              <1> ;m17:
  2385 000014F2 C3                  <1> 	retn
  2386                              <1> m17:
  2387                              <1> 	; 14/06/2022
  2388                              <1> 	; ('write_tty' must not return to 'putc' with cf)
  2389 000014F3 F8                  <1> 	clc
  2390 000014F4 C3                  <1> 	retn
  2391                              <1> 
  2392                              <1> set_ctype:
  2393                              <1> 	; 07/02/2022
  2394                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2395                              <1> 	;
  2396                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2397                              <1> 
  2398                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2399                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2400                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2401                              <1> ;          OR NO CURSOR AT ALL
  2402                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2403                              <1> 
  2404                              <1> ;------------------------------------------------
  2405                              <1> ; SET_CTYPE
  2406                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2407                              <1> ; INPUT
  2408                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2409                              <1> ; OUTPUT	
  2410                              <1> ;	NONE
  2411                              <1> ;------------------------------------------------
  2412                              <1> 
  2413 000014F5 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2414                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2415                              <1> 	;call	m16	; output cx register
  2416                              <1> 	;retn
  2417                              <1> 	; 07/02/2022
  2418 000014F7 EBDB                <1> 	jmp	short m16
  2419                              <1> 
  2420                              <1> position:
  2421                              <1> 	; 23/02/2022
  2422                              <1> 	; 02/02/2022
  2423                              <1> 	; 27/06/2015
  2424                              <1> 	; 02/09/2014
  2425                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2426                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2427                              <1> 	;
  2428                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2429                              <1> 	;
  2430                              <1> 	; POSITION
  2431                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2432                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2433                              <1> 	; INPUT
  2434                              <1> 	;	AX = ROW, COLUMN POSITION
  2435                              <1> 	; OUTPUT
  2436                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2437                              <1> 
  2438                              <1> 		; DX = ROW, COLUMN POSITION
  2439                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2440 000014F9 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2441 000014FB B050                <1> 	mov	al, 80	; determine bytes to row	
  2442 000014FD F6E6                <1> 	mul	dh	; row value
  2443                              <1> 	;xor	dh, dh	; 0
  2444                              <1> 	;add	ax, dx	; add column value to the result
  2445                              <1> 	; 23/02/2022
  2446 000014FF 00D0                <1> 	add	al, dl
  2447 00001501 80D400              <1> 	adc	ah, 0	
  2448                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2449                              <1> 	; 02/02/2022
  2450 00001504 D1E0                <1> 	shl	eax, 1
  2451                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2452 00001506 C3                  <1> 	retn
  2453                              <1> 
  2454                              <1> find_position:
  2455                              <1> 	; 02/02/2022
  2456                              <1> 	; 27/06/2015
  2457                              <1> 	; 07/09/2014
  2458                              <1> 	; 02/09/2014
  2459                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2460                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2461 00001507 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2462 0000150A 89CE                <1> 	mov	esi, ecx
  2463                              <1> 	;shl	si, 1
  2464                              <1> 	; 02/02/2022
  2465 0000150C D1E6                <1> 	shl	esi, 1
  2466 0000150E 668B96[46680000]    <1> 	mov	dx, [esi+cursor_posn]
  2467 00001515 7409                <1> 	jz	short p21
  2468                              <1> 	;xor	si, si
  2469                              <1> 	; 02/02/2022
  2470 00001517 31F6                <1> 	xor	esi, esi
  2471                              <1> p20:
  2472                              <1> 	;add	si, [CRT_LEN]
  2473 00001519 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2474 0000151E E2F9                <1> 	loop	p20
  2475                              <1> p21:
  2476 00001520 6621D2              <1> 	and	dx, dx
  2477 00001523 7407                <1> 	jz	short p22
  2478 00001525 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2479 0000152A 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2480                              <1> p22:	
  2481                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2482                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2483                              <1> 	;add	dx, 6	; point at status port
  2484 0000152C 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2485                              <1> 	; cx = 0
  2486 00001530 C3                  <1> 	retn
  2487                              <1> 
  2488                              <1> scroll_up:
  2489                              <1> 	; 02/02/2022 (simplified scroll up)
  2490                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2491                              <1> 	; 16/01/2016
  2492                              <1> 	; 07/09/2014
  2493                              <1> 	; 02/09/2014
  2494                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2495                              <1> 	; 04/04/2014
  2496                              <1> 	; 04/12/2013
  2497                              <1> 	;
  2498                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2499                              <1> 	;
  2500                              <1> 	; SCROLL UP
  2501                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2502                              <1> 	;	ON THE SCREEN
  2503                              <1> 	; INPUT
  2504                              <1> 	;	(AH) = CURRENT CRT MODE
  2505                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2506                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2507                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2508                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2509                              <1> 	;	(DS) = DATA SEGMENT
  2510                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2511                              <1> 	; OUTPUT
  2512                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2513                              <1> 	;
  2514                              <1> 	;	bh = 0  (02/09/2014)
  2515                              <1> 	;
  2516                              <1> 	; ((ah = 3))
  2517                              <1> 	; cl = left upper column
  2518                              <1> 	; ch = left upper row
  2519                              <1> 	; dl = right lower column
  2520                              <1> 	; dh = right lower row
  2521                              <1> 	;
  2522                              <1> 	; al = line count 
  2523                              <1> 	; ah = attribute to be used on blanked line
  2524                              <1> 	; bl = video page number (0 to 7)
  2525                              <1> 	; 
  2526                              <1> 
  2527                              <1> 	; 02/02/2022 'scroll_up' code
  2528                              <1> 	; ------------------------------------------------------
  2529                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2530                              <1> 
  2531                              <1> 	; INPUT:
  2532                              <1> 	;		
  2533                              <1> 	; al = line count 
  2534                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2535                              <1> 	; ah = attribute to be used on blanked line
  2536                              <1> 	; bl = video page number (0 to 7)
  2537                              <1> 
  2538                              <1> 	;cli
  2539 00001531 31C9                <1> 	xor	ecx, ecx
  2540 00001533 88C1                <1> 	mov	cl, al ; line count (cl)
  2541 00001535 BE00800B00          <1> 	mov	esi, 0B8000h
  2542 0000153A 3A1D[56680000]      <1> 	cmp	bl, [active_page]
  2543 00001540 7411                <1> 	je	short n1
  2544 00001542 20DB                <1> 	and	bl, bl
  2545 00001544 7422                <1> 	jz	short n3
  2546 00001546 88DD                <1> 	mov	ch, bl ; video page number
  2547                              <1> n0:
  2548 00001548 6681C6A00F          <1> 	add	si, 25*80*2
  2549 0000154D FECD                <1> 	dec	ch
  2550 0000154F 75F7                <1> 	jnz	short n0
  2551 00001551 EB15                <1> 	jmp	short n3
  2552                              <1> n1:
  2553 00001553 660335[44680000]    <1> 	add	si, [CRT_START]
  2554                              <1> 	;
  2555 0000155A 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2556                              <1> n2:			 ; wait_display_enable
  2557 0000155E EC                  <1> 	in	al, dx	 ; get port
  2558 0000155F A808                <1> 	test	al, RVRT ; wait for vertical retrace
  2559 00001561 74FB                <1> 	jz	short n2 ; wait_display_enable
  2560 00001563 B025                <1> 	mov	al, 25h
  2561 00001565 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2562 00001567 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2563                              <1> n3:
  2564                              <1> 	; cl = line count
  2565                              <1> 	; ah = attribute/color
  2566 00001568 89F7                <1> 	mov	edi, esi
  2567 0000156A 20C9                <1> 	and	cl, cl
  2568 0000156C 741F                <1> 	jz	short n6
  2569 0000156E 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2570 00001573 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2571 00001577 F366A5              <1> 	rep	movsw
  2572 0000157A B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2573                              <1> n4:
  2574                              <1> 	; ah = character attribute/cocor
  2575 0000157C B020                <1> 	mov	al, 20h ; fill with blanks
  2576 0000157E F366AB              <1> 	rep	stosw
  2577                              <1> 
  2578 00001581 3A1D[56680000]      <1> 	cmp	bl, [active_page]
  2579 00001587 7503                <1> 	jne	short n5
  2580                              <1> 
  2581                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2582 00001589 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2583                              <1> 	;mov	dx, 03D8h ; always set color card port
  2584 0000158B EE                  <1> 	out	dx, al
  2585                              <1> n5:
  2586 0000158C C3                  <1> 	retn
  2587                              <1> n6:
  2588                              <1> 	; clear video page
  2589 0000158D 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2590 00001591 EBE9                <1> 	jmp	short n4
  2591                              <1> 
  2592                              <1> 	; 23/02/2022
  2593                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2594                              <1> 	; ------------------------------------------------------
  2595                              <1> 
  2596                              <1> 	; Test	Line Count
  2597                              <1> 	or	al, al
  2598                              <1> 	jz	short al_set
  2599                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2600                              <1> 	sub	bh, ch
  2601                              <1> 	inc	bh	; adjust difference by 1
  2602                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2603                              <1> 	jne	short al_set ; if not the we're all set
  2604                              <1> 	xor	al, al	; otherwise set al to zero
  2605                              <1> al_set:
  2606                              <1> 	xor	bh, bh	; 0
  2607                              <1> 	;push	ax
  2608                              <1> 	push	eax ; 23/02/2022
  2609                              <1> 	;mov 	esi, [crt_base]
  2610                              <1>         mov     esi, 0B8000h  
  2611                              <1>         cmp     bl, [active_page]
  2612                              <1> 	jne	short n0
  2613                              <1> 	;
  2614                              <1>         mov     ax, [CRT_START]
  2615                              <1>         add     si, ax
  2616                              <1>         jmp     short n1
  2617                              <1> n0:
  2618                              <1>         and     bl, bl
  2619                              <1> 	jz	short n1
  2620                              <1> 	mov	al, bl
  2621                              <1> n0x:
  2622                              <1>         ;add    si, [CRT_LEN]
  2623                              <1>         ;add    esi, 80*25*2 
  2624                              <1>         add     si, 80*25*2
  2625                              <1>         dec	al
  2626                              <1> 	jnz	short n0x
  2627                              <1> n1:	
  2628                              <1>         ; Scroll position
  2629                              <1> 	;push	dx ; 23/02/2022
  2630                              <1> 	mov	dx, cx	; now, upper left position in DX
  2631                              <1> 	call	position
  2632                              <1> 	add	esi, eax
  2633                              <1> 	mov	edi, esi
  2634                              <1> 	;pop	dx	; lower right position in DX
  2635                              <1> 	sub	dx, cx
  2636                              <1> 	inc	dh	; dh = #rows 
  2637                              <1> 	inc	dl	; dl = #cols in block
  2638                              <1> 	;pop	ax	; al = line count, ah = attribute
  2639                              <1> 	pop	eax ; 23/02/2022
  2640                              <1> 	xor	ecx, ecx
  2641                              <1> 	mov	cx, ax
  2642                              <1> 	;mov	ah, [CRT_COLS]
  2643                              <1> 	mov	ah, 80
  2644                              <1> 	mul	ah	; determine offset to from address
  2645                              <1> 	add	ax, ax  ; *2 for attribute byte
  2646                              <1> 	;
  2647                              <1> 	;push	ax	; offset 
  2648                              <1> 	;push	dx
  2649                              <1> 	; 23/02/2022
  2650                              <1> 	push	eax
  2651                              <1> 	push	edx
  2652                              <1> 	;
  2653                              <1> 	; 04/04/2014
  2654                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2655                              <1> n8:                      ; wait_display_enable
  2656                              <1>         in      al, dx   ; get port
  2657                              <1> 	test	al, RVRT ; wait for vertical retrace
  2658                              <1> 	jz	short n8 ; wait_display_enable
  2659                              <1> 	mov	al, 25h
  2660                              <1> 	mov	dl, 0D8h ; address control port
  2661                              <1> 	out	dx, al	; turn off video during vertical retrace
  2662                              <1> 	;pop	dx	; #rows, #cols
  2663                              <1>        	;pop	ax	; offset
  2664                              <1> 	; 23/02/2022
  2665                              <1> 	pop	edx
  2666                              <1> 	pop	eax
  2667                              <1> 	xchg	ax, cx	; 
  2668                              <1> 	; ecx = offset, al = line count, ah = attribute
  2669                              <1> ;n9:
  2670                              <1> 	or	al, al
  2671                              <1>         jz      short n3 
  2672                              <1>         add     esi, ecx ; from address for scroll
  2673                              <1> 	mov	bh, dh  ; #rows in block
  2674                              <1> 	sub	bh, al	; #rows to be moved
  2675                              <1> n2:
  2676                              <1> 	; Move rows
  2677                              <1> 	mov	cl, dl	; get # of cols to move
  2678                              <1> 	push	esi
  2679                              <1> 	push	edi	; save start address
  2680                              <1> n10:
  2681                              <1> 	movsw		; move that line on screen
  2682                              <1> 	dec	cl
  2683                              <1>         jnz     short n10
  2684                              <1> 	pop	edi
  2685                              <1> 	pop	esi	; recover addresses
  2686                              <1>         ;mov    cl, [CRT_COLS] 
  2687                              <1> 	;add	cl, cl
  2688                              <1>         ;mov    ecx, 80*2
  2689                              <1>         mov     cx, 80*2
  2690                              <1>         add     esi, ecx  ; next line
  2691                              <1>         add     edi, ecx
  2692                              <1> 	dec	bh	 ; count of lines to move
  2693                              <1> 	jnz	short n2 ; row loop
  2694                              <1> 	; bh = 0
  2695                              <1> 	mov	dh, al	 ; #rows	
  2696                              <1> n3:
  2697                              <1> 	; attribute in ah
  2698                              <1> 	mov	al, ' '	 ; fill with blanks
  2699                              <1> n3x:
  2700                              <1> 	; Clear rows
  2701                              <1>                 ; dh =  #rows
  2702                              <1>         mov	cl, dl	; get # of cols to clear
  2703                              <1>         push    edi     ; save address
  2704                              <1> n11:
  2705                              <1>         stosw           ; store fill character
  2706                              <1> 	dec	cl
  2707                              <1>         jnz     short n11
  2708                              <1>         pop     edi     ; recover address
  2709                              <1> 	;mov	cl, [CRT_COLS]
  2710                              <1> 	;add	cl, cl
  2711                              <1>         ;mov    ecx, 80*2
  2712                              <1>         mov	cl, 80*2
  2713                              <1>         add     edi, ecx
  2714                              <1> 	dec	dh
  2715                              <1> 	jnz	short n3x ; 16/01/2016
  2716                              <1> 	;
  2717                              <1> 	cmp	bl, [active_page]
  2718                              <1> 	jne	short n6
  2719                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2720                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2721                              <1> 	mov	dx, 03D8h ; always set color card port
  2722                              <1> 	out	dx, al
  2723                              <1> n6:
  2724                              <1> 	retn
  2725                              <1> 
  2726                              <1> %endif
  2727                              <1> 
  2728                              <1> write_c_current:
  2729                              <1> 	; 02/02/2022
  2730                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2731                              <1> 	; 18/01/2014
  2732                              <1> 	; 04/12/2013
  2733                              <1> 	;
  2734                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2735                              <1> 	;
  2736                              <1> 	; WRITE_C_CURRENT
  2737                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2738                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2739                              <1> 	; INPUT	
  2740                              <1> 	;	(AH) = CURRENT CRT MODE
  2741                              <1> 	;	(BH) = DISPLAY PAGE
  2742                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2743                              <1> 	;	(AL) = CHAR TO WRITE
  2744                              <1> 	;	(DS) = DATA SEGMENT
  2745                              <1> 	;	(ES) = REGEN SEGMENT
  2746                              <1> 	; OUTPUT
  2747                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2748                              <1> 
  2749 00001593 FA                  <1> 	cli		
  2750                              <1> 	; bl = video page
  2751                              <1> 	; al = character
  2752                              <1> 	; ah = color/attribute
  2753                              <1> 	;push	dx
  2754                              <1> 	;push	ax	; save character & attribute/color
  2755                              <1> 	; 02/02/2022
  2756 00001594 52                  <1> 	push	edx
  2757 00001595 50                  <1> 	push	eax
  2758 00001596 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2759                              <1> 	; esi = regen location
  2760                              <1> 	; dx = status port
  2761                              <1> 	;
  2762                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2763                              <1> 	;
  2764                              <1> p41:			; wait for horizontal retrace is low or vertical
  2765 0000159B FB                  <1> 	sti		; enable interrupts first
  2766 0000159C 3A1D[56680000]      <1>         cmp     bl, [active_page]
  2767 000015A2 7510                <1> 	jne	short p44 
  2768 000015A4 FA                  <1> 	cli 		; block interrupts for single loop
  2769 000015A5 EC                  <1> 	in	al, dx	; get status from the adapter
  2770 000015A6 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2771 000015A8 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2772 000015AA A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2773 000015AC 75ED                <1> 	jnz	short p41 ; wait until it is
  2774                              <1> p42:			; wait for either retrace high
  2775 000015AE EC                  <1> 	in	al, dx	; get status again
  2776 000015AF A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2777 000015B1 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2778                              <1> p43:	
  2779 000015B3 FB                  <1> 	sti
  2780                              <1> p44:
  2781                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2782                              <1> 	; 02/02/2022
  2783 000015B4 58                  <1> 	pop	eax
  2784 000015B5 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2785                              <1> 			; Retro UNIX 386 v1 feature only!
  2786 000015BB 668906              <1> 	mov	[esi], ax
  2787                              <1> 	;pop	dx
  2788                              <1> 	; 02/02/2022
  2789 000015BE 5A                  <1> 	pop	edx
  2790 000015BF C3                  <1> 	retn
  2791                              <1> 
  2792                              <1> %if 0	; 02/02/2022
  2793                              <1> 
  2794                              <1> set_mode:
  2795                              <1> 	; 02/02/2022
  2796                              <1> 	; 16/01/2016
  2797                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2798                              <1> 	;
  2799                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2800                              <1> 
  2801                              <1> ;------------------------------------------------------
  2802                              <1> ; SET MODE					      :
  2803                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2804                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2805                              <1> ; INPUT						      :
  2806                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2807                              <1> ; OUTPUT					      :
  2808                              <1> ;	NONE					      :
  2809                              <1> ;------------------------------------------------------
  2810                              <1> 
  2811                              <1> 	push	edi ; 16/01/2016
  2812                              <1> 	push	ebx
  2813                              <1> 	push	edx
  2814                              <1> 	push	ecx ; 16/01/2016
  2815                              <1>         push    eax
  2816                              <1> 
  2817                              <1> 	;mov	dx, 03D4h 	; address or color card
  2818                              <1> 	mov	al, 3
  2819                              <1> ;M8:
  2820                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2821                              <1> 	mov	al, 29h
  2822                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2823                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2824                              <1> 	;push	dx  		; save port value
  2825                              <1> 	;add	dx, 4		; point to control register
  2826                              <1> 	mov	dx, 3D8h
  2827                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2828                              <1> 	;pop	dx
  2829                              <1> ;M9:
  2830                              <1> 	mov	ebx, video_params ; initialization table
  2831                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2832                              <1> 	;xchg 	ah, al
  2833                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2834                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2835                              <1> 	
  2836                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2837                              <1> 	; 02/02/2022
  2838                              <1> 	; dx = 3D8h
  2839                              <1> 	xor	ecx, ecx
  2840                              <1> 	mov	cl, 16
  2841                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2842                              <1> M10:			;  initialization loop
  2843                              <1> 	mov	al, ah 	; get 6845 register number
  2844                              <1> 	out	dx, al
  2845                              <1> 	;inc	dx      ; point to data port
  2846                              <1> 	; 02/02/2022
  2847                              <1> 	inc	dl ; 3D9h
  2848                              <1> 	inc	ah	; next register value
  2849                              <1> 	mov	al, [ebx] ; get table value
  2850                              <1> 	out	dx, al	; out to chip
  2851                              <1> 	inc	ebx	; next in table
  2852                              <1> 	;dec	dx	; back to pointer register
  2853                              <1> 	; 02/02/2022
  2854                              <1> 	dec	dl ; 3D8h
  2855                              <1> 	loop	M10	; do the whole table
  2856                              <1> 	
  2857                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2858                              <1> 	;xor	ax, ax  
  2859                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2860                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2861                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2862                              <1> 	; black background, light gray characeter color, space character
  2863                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2864                              <1> ;M13:			  ; clear buffer
  2865                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2866                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2867                              <1> 
  2868                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2869                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2870                              <1> 			 ; prepare to output to video enable port
  2871                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2872                              <1> 	; 02/02/2022
  2873                              <1> 	;mov	dx, 3D8h
  2874                              <1> 	; 
  2875                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2876                              <1> 	mov	al, 29h
  2877                              <1> 	out	dx, al	 ; set video enable port
  2878                              <1> 
  2879                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2880                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2881                              <1> 	;
  2882                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2883                              <1> 	;
  2884                              <1> ;-----	SET CURSOR POSITIONS
  2885                              <1> 	;push	edi
  2886                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2887                              <1> 	mov	edi, cursor_posn
  2888                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2889                              <1> 	xor	eax, eax
  2890                              <1> 	rep 	stosd	; fill with zeroes
  2891                              <1> 	;pop	edi
  2892                              <1> 
  2893                              <1> ;-----	SET UP OVERSCAN REGISTER
  2894                              <1> 	inc	dx	; set overscan port to a default
  2895                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2896                              <1> ;M14:
  2897                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2898                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2899                              <1> 
  2900                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2901                              <1> 	;
  2902                              <1> 	pop	eax
  2903                              <1> 	pop	ecx ; 16/01/2016
  2904                              <1> 	pop	edx
  2905                              <1> 	pop	ebx
  2906                              <1> 	pop	edi ; 16/01/2016
  2907                              <1> 	retn
  2908                              <1> 
  2909                              <1> %endif
  2910                              <1> 	
  2911                              <1> tty_sw:
  2912                              <1> 	; 02/02/2022
  2913                              <1> 	; 30/06/2015
  2914                              <1> 	; 27/06/2015 
  2915                              <1> 	; 07/09/2014
  2916                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2917                              <1> 	;
  2918                              <1> 	; (Modified registers : EAX)
  2919                              <1> 	;
  2920                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2921                              <1> 	;
  2922                              <1> ;act_disp_page:
  2923                              <1> 	; 30/06/2015
  2924                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2925                              <1> 	; 10/12/2013
  2926                              <1> 	; 04/12/2013
  2927                              <1> 	;
  2928                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2929                              <1> 	;
  2930                              <1> 	; ACT_DISP_PAGE
  2931                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2932                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2933                              <1> 	; INPUT
  2934                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2935                              <1> 	; OUTPUT
  2936                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2937                              <1> 
  2938                              <1> 	;cli
  2939                              <1> 
  2940 000015C0 53                  <1> 	push	ebx
  2941                              <1> 	;push	cx
  2942                              <1> 	;push	dx
  2943                              <1> 	; 02/02/2022
  2944 000015C1 51                  <1> 	push	ecx
  2945 000015C2 52                  <1> 	push	edx
  2946                              <1> 	;
  2947 000015C3 A2[56680000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2948                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2949                              <1> 	;mov	cx, 25*80*2
  2950                              <1> 	; 02/02/2022
  2951 000015C8 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2952                              <1> 	; 27/06/2015
  2953 000015CD 0FB6D8              <1> 	movzx	ebx, al
  2954                              <1> 	; 02/02/2022
  2955 000015D0 89D8                <1> 	mov	eax, ebx
  2956                              <1> 	;
  2957                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2958                              <1> 	;mul 	cx	; display page times regen length
  2959                              <1> 	; 02/02/2022
  2960 000015D2 F7E1                <1> 	mul	ecx	
  2961                              <1> 	; 10/12/2013
  2962 000015D4 66A3[44680000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2963                              <1> 	;mov	cx, ax	; start address to cx
  2964                              <1> 	; 02/02/2022
  2965 000015DA 89C1                <1> 	mov	ecx, eax
  2966                              <1> 	;;sar	cx, 1
  2967                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2968                              <1> 	; 02/02/2022
  2969 000015DC D1E9                <1> 	shr	ecx, 1
  2970 000015DE B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2971 000015E0 E8EFFEFFFF          <1> 	call	m16
  2972                              <1> 	;sal	bx, 1
  2973                              <1> 	; 01/09/2014
  2974 000015E5 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2975 000015E7 81C3[46680000]      <1> 	add	ebx, cursor_posn
  2976 000015ED 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2977 000015F0 E8CDFEFFFF          <1> 	call	m18
  2978                              <1> 	;
  2979                              <1> 	;pop	dx
  2980                              <1> 	;pop	cx
  2981                              <1> 	; 02/02/2022
  2982 000015F5 5A                  <1> 	pop	edx
  2983 000015F6 59                  <1> 	pop	ecx
  2984 000015F7 5B                  <1> 	pop	ebx
  2985                              <1> 	;
  2986                              <1> 	;sti
  2987                              <1> 	;
  2988 000015F8 C3                  <1> 	retn
  2989                              <1> 
  2990                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2991                              <1> 
  2992                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1867                                  
  1868                                  setup_rtc_int:
  1869                                  ; source: http://wiki.osdev.org/RTC
  1870 000015F9 FA                      	cli		; disable interrupts
  1871                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1872                                  	; in order to change this ...
  1873                                  	; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1874                                  	; (rate must be above 2 and not over 15)
  1875                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1876 000015FA B08A                    	mov	al, 8Ah 
  1877 000015FC E670                    	out	70h, al ; set index to register A, disable NMI
  1878 000015FE 90                      	nop
  1879 000015FF E471                    	in	al, 71h ; get initial value of register A
  1880 00001601 88C4                    	mov 	ah, al
  1881 00001603 80E4F0                  	and	ah, 0F0h
  1882 00001606 B08A                    	mov	al, 8Ah 
  1883 00001608 E670                    	out	70h, al ; reset index to register A
  1884 0000160A 88E0                    	mov	al, ah
  1885 0000160C 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1886 0000160E E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1887                                  	; enable RTC interrupt
  1888 00001610 B08B                    	mov	al, 8Bh ;
  1889 00001612 E670                    	out	70h, al ; select register B and disable NMI
  1890 00001614 90                      	nop
  1891 00001615 E471                    	in	al, 71h ; read the current value of register B
  1892 00001617 88C4                    	mov	ah, al  ;
  1893 00001619 B08B                    	mov 	al, 8Bh ;
  1894 0000161B E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1895 0000161D 88E0                    	mov	al, ah  ;
  1896 0000161F 0C40                    	or	al, 40h ;
  1897 00001621 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1898 00001623 FB                      	sti
  1899 00001624 C3                      	retn
  1900                                  
  1901                                  ; Write memory information
  1902                                  ; Temporary Code
  1903                                  ; 06/11/2014
  1904                                  ; 14/08/2015 
  1905                                  memory_info:	
  1906 00001625 A1[2C680000]            	mov	eax, [memory_size] ; in pages
  1907 0000162A 50                      	push	eax
  1908 0000162B C1E00C                  	shl	eax, 12		   ; in bytes
  1909 0000162E BB0A000000              	mov	ebx, 10
  1910 00001633 89D9                    	mov	ecx, ebx	   ; 10
  1911 00001635 BE[95640000]            	mov	esi, mem_total_b_str	
  1912 0000163A E8AE000000              	call	bintdstr
  1913 0000163F 58                      	pop	eax
  1914 00001640 B107                    	mov	cl, 7
  1915 00001642 BE[B9640000]            	mov	esi, mem_total_p_str
  1916 00001647 E8A1000000              	call	bintdstr	
  1917                                  	; 14/08/2015
  1918 0000164C E8B9000000              	call	calc_free_mem
  1919                                  	; edx = calculated free pages
  1920                                  	; ecx = 0
  1921 00001651 A1[30680000]            	mov 	eax, [free_pages]
  1922 00001656 39D0                    	cmp	eax, edx ; calculated free mem value 
  1923                                  		; and initial free mem value are same or not?
  1924 00001658 751D                    	jne 	short pmim ; print mem info with '?' if not
  1925 0000165A 52                      	push 	edx ; free memory in pages	
  1926                                  	;mov 	eax, edx
  1927 0000165B C1E00C                  	shl	eax, 12 ; convert page count
  1928                                  			; to byte count
  1929 0000165E B10A                    	mov	cl, 10
  1930 00001660 BE[D9640000]            	mov	esi, free_mem_b_str
  1931 00001665 E883000000              	call	bintdstr
  1932 0000166A 58                      	pop	eax
  1933 0000166B B107                    	mov	cl, 7
  1934 0000166D BE[FD640000]            	mov	esi, free_mem_p_str
  1935 00001672 E876000000              	call	bintdstr
  1936                                  pmim:
  1937 00001677 BE[83640000]            	mov	esi, msg_memory_info
  1938                                  pmim_nb:	
  1939 0000167C AC                      	lodsb
  1940 0000167D 08C0                    	or	al, al
  1941 0000167F 740D                    	jz	short pmim_ok
  1942 00001681 56                      	push	esi
  1943 00001682 31DB                    	xor	ebx, ebx ; 0
  1944                                  			; Video page 0 (bl=0)
  1945 00001684 B407                    	mov	ah, 07h ; Black background, 
  1946                                  			; light gray forecolor
  1947 00001686 E816FDFFFF              	call	write_tty
  1948 0000168B 5E                      	pop	esi
  1949 0000168C EBEE                    	jmp	short pmim_nb
  1950                                  pmim_ok:
  1951 0000168E C3                      	retn
  1952                                  
  1953                                  ; Convert binary number to hexadecimal string
  1954                                  ; 10/05/2015  
  1955                                  ; dsectpm.s (28/02/2015)
  1956                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1957                                  ; 01/12/2014
  1958                                  ; 25/11/2014
  1959                                  ;
  1960                                  bytetohex:
  1961                                  	; INPUT ->
  1962                                  	; 	AL = byte (binary number)
  1963                                  	; OUTPUT ->
  1964                                  	;	AX = hexadecimal string
  1965                                  	;
  1966 0000168F 53                      	push	ebx
  1967 00001690 31DB                    	xor	ebx, ebx
  1968 00001692 88C3                    	mov	bl, al
  1969 00001694 C0EB04                  	shr	bl, 4
  1970 00001697 8A9B[DD160000]          	mov	bl, [ebx+hexchrs]
  1971 0000169D 86D8                    	xchg	bl, al
  1972 0000169F 80E30F                  	and	bl, 0Fh
  1973 000016A2 8AA3[DD160000]          	mov	ah, [ebx+hexchrs]
  1974 000016A8 5B                      	pop	ebx	
  1975 000016A9 C3                      	retn
  1976                                  
  1977                                  wordtohex:
  1978                                  	; INPUT ->
  1979                                  	; 	AX = word (binary number)
  1980                                  	; OUTPUT ->
  1981                                  	;	EAX = hexadecimal string
  1982                                  	;
  1983 000016AA 53                      	push	ebx
  1984 000016AB 31DB                    	xor	ebx, ebx
  1985 000016AD 86E0                    	xchg	ah, al
  1986 000016AF 6650                    	push	ax
  1987 000016B1 88E3                    	mov	bl, ah
  1988 000016B3 C0EB04                  	shr	bl, 4
  1989 000016B6 8A83[DD160000]          	mov	al, [ebx+hexchrs]
  1990 000016BC 88E3                    	mov	bl, ah
  1991 000016BE 80E30F                  	and	bl, 0Fh
  1992 000016C1 8AA3[DD160000]          	mov	ah, [ebx+hexchrs]
  1993 000016C7 C1E010                  	shl	eax, 16
  1994 000016CA 6658                    	pop	ax
  1995 000016CC 5B                      	pop	ebx
  1996 000016CD EBC0                    	jmp	short bytetohex
  1997                                  	;mov	bl, al
  1998                                  	;shr	bl, 4
  1999                                  	;mov	bl, [ebx+hexchrs]
  2000                                  	;xchg	bl, al	 	
  2001                                  	;and	bl, 0Fh
  2002                                  	;mov	ah, [ebx+hexchrs]
  2003                                  	;pop	ebx	
  2004                                  	;retn
  2005                                  
  2006                                  dwordtohex:
  2007                                  	; INPUT ->
  2008                                  	; 	EAX = dword (binary number)
  2009                                  	; OUTPUT ->
  2010                                  	;	EDX:EAX = hexadecimal string
  2011                                  	;
  2012 000016CF 50                      	push	eax
  2013 000016D0 C1E810                  	shr	eax, 16
  2014 000016D3 E8D2FFFFFF              	call	wordtohex
  2015 000016D8 89C2                    	mov	edx, eax
  2016 000016DA 58                      	pop	eax
  2017                                  	;call	wordtohex
  2018                                  	;retn
  2019                                  	; 02/01/2022
  2020 000016DB EBCD                    	jmp	short wordtohex
  2021                                  
  2022                                  ; 10/05/2015
  2023                                  hex_digits:
  2024                                  hexchrs:
  2025 000016DD 303132333435363738-     	db '0123456789ABCDEF'
  2025 000016E6 39414243444546     
  2026                                  
  2027                                  ; Convert binary number to decimal/numeric string
  2028                                  ; 06/11/2014
  2029                                  ; Temporary Code
  2030                                  ;
  2031                                  
  2032                                  bintdstr:
  2033                                  	; EAX = binary number
  2034                                  	; ESI = decimal/numeric string address
  2035                                  	; EBX = divisor (10)
  2036                                  	; ECX = string length (<=10)
  2037 000016ED 01CE                    	add	esi, ecx
  2038                                  btdstr0:
  2039 000016EF 4E                      	dec	esi
  2040 000016F0 31D2                    	xor	edx, edx
  2041 000016F2 F7F3                    	div	ebx
  2042 000016F4 80C230                  	add	dl, 30h
  2043 000016F7 8816                    	mov	[esi], dl
  2044 000016F9 FEC9                    	dec	cl
  2045 000016FB 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2046 000016FD 09C0                    	or	eax, eax
  2047 000016FF 75EE                    	jnz	short btdstr0
  2048                                  btdstr1:
  2049 00001701 4E                      	dec	esi
  2050 00001702 C60620                          mov     byte [esi], 20h ; blank space
  2051 00001705 FEC9                    	dec	cl
  2052 00001707 75F8                    	jnz	short btdstr1
  2053                                  btdstr2:
  2054 00001709 C3                      	retn
  2055                                  
  2056                                  ; Calculate free memory pages on M.A.T.
  2057                                  ; 06/11/2014
  2058                                  ; Temporary Code
  2059                                  ;
  2060                                  
  2061                                  calc_free_mem:
  2062 0000170A 31D2                    	xor	edx, edx
  2063                                  	;xor	ecx, ecx
  2064                                  	;mov	cx, [mat_size] ; in pages
  2065                                  	; 02/01/2022
  2066 0000170C 8B0D[40680000]          	mov	ecx, [mat_size] ; in pages
  2067 00001712 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2068 00001715 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2069                                  cfm0:
  2070 0000171A AD                      	lodsd
  2071 0000171B 51                      	push	ecx
  2072 0000171C B920000000              	mov	ecx, 32
  2073                                  cfm1:
  2074 00001721 D1E8                    	shr	eax, 1
  2075 00001723 7301                    	jnc	short cfm2
  2076 00001725 42                      	inc	edx
  2077                                  cfm2:
  2078 00001726 E2F9                    	loop	cfm1
  2079 00001728 59                      	pop	ecx
  2080 00001729 E2EF                    	loop	cfm0
  2081 0000172B C3                      	retn
  2082                                  
  2083                                  %include 'diskio.s'  ; 07/03/2015
  2084                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2085                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2086                              <1> ; ****************************************************************************
  2087                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2088                              <1> 
  2089                              <1> ; Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2090                              <1> ; Last Modification: 16/07/2022
  2091                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2092                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2093                              <1> ;
  2094                              <1> ; ****************************************************************************
  2095                              <1> ; Ref: Retro UNIX 386 v1.1 Kernel (v0.2.1.5) - DISKIO.INC
  2096                              <1> 
  2097                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2098                              <1> 
  2099                              <1> ; 11/07/2022
  2100                              <1> ;; 06/02/2015
  2101                              <1> ;diskette_io:
  2102                              <1> ;	pushfd
  2103                              <1> ;	push 	cs
  2104                              <1> ;	call 	DISKETTE_IO_1
  2105                              <1> ;	retn
  2106                              <1> 	
  2107                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2108                              <1> ;//////////////////////////////////////////////////////
  2109                              <1> 
  2110                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2111                              <1> ;		Function in AL
  2112                              <1> ;			0 = reset
  2113                              <1> ;			1 = read
  2114                              <1> ;			2 = write
  2115                              <1> ;		Disk drive number in DL
  2116                              <1> ;			0 & 1 = floppy disks	
  2117                              <1> ;			80h .. 83h = hard disks
  2118                              <1> ;		Sector address (LBA) in ECX
  2119                              <1> ;		Buffer address in EBX
  2120                              <1> ;		R/W sector count is (always) 1
  2121                              <1> ;
  2122                              <1> ;		Return:
  2123                              <1> ;			Status in AH (>0 = error code)
  2124                              <1> ;			if CF = 1 -> error code in AH
  2125                              <1> ;			if CF = 0 -> successful
  2126                              <1> ;			AL = undefined
  2127                              <1> ;
  2128                              <1> ;		Modified registers: (only) EAX
  2129                              <1> 
  2130                              <1> ; 10/07/2022
  2131                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2132                              <1> ;		by removing unused IBM PC-AT disk functions)
  2133                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2134                              <1> ; 20/02/2015
  2135                              <1> ; 06/02/2015 (unix386.s)
  2136                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2137                              <1> ;
  2138                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2139                              <1> ;
  2140                              <1> ; ADISK.EQU
  2141                              <1> 
  2142                              <1> ;----- Wait control constants 
  2143                              <1> 
  2144                              <1> ;amount of time to wait while RESET is active.
  2145                              <1> 
  2146                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2147                              <1> 					;at 250 KBS xfer rate.
  2148                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2149                              <1> 
  2150                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2151                              <1> 					;status register to become valid
  2152                              <1> 					;before re-reading.
  2153                              <1> 
  2154                              <1> ;After sending a byte to NEC, status register may remain
  2155                              <1> ;incorrectly set for 24 us.
  2156                              <1> 
  2157                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2158                              <1> 					;RQM low.
  2159                              <1> 
  2160                              <1> ; COMMON.MAC
  2161                              <1> ;
  2162                              <1> ;	Timing macros
  2163                              <1> ;
  2164                              <1> 
  2165                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2166                              <1> 		jmp short $+2
  2167                              <1> %endmacro		
  2168                              <1> 
  2169                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2170                              <1> 		jmp short $+2
  2171                              <1> 		jmp short $+2
  2172                              <1> %endmacro
  2173                              <1> 
  2174                              <1> %macro		NEWIODELAY 0
  2175                              <1> 		out 0EBh,al
  2176                              <1> %endmacro 
  2177                              <1> 
  2178                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2179                              <1> ;;; WAIT_FOR_MEM
  2180                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2181                              <1> ;WAIT_FDU_INT_HI	equ	1
  2182                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2183                              <1> ;;; WAIT_FOR_PORT
  2184                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2185                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2186                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2187                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2188                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2189                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2190                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2191                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2192                              <1> ;;; WAIT_REFRESH
  2193                              <1> ;amount of time to wait for head settle, per unit in parameter
  2194                              <1> ;table = 1 ms.
  2195                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2196                              <1> 
  2197                              <1> 
  2198                              <1> ; //////////////// DISKETTE I/O ////////////////
  2199                              <1> 
  2200                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2201                              <1> 
  2202                              <1> ;----------------------------------------
  2203                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2204                              <1> ;----------------------------------------
  2205                              <1> 
  2206                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2207                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2208                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2209                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2210                              <1> 
  2211                              <1> ;----------------------------------------
  2212                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2213                              <1> ;-------------------------------------------------------------------------------
  2214                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2215                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2216                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2217                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2218                              <1> 
  2219                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2220                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2221                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2222                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2223                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2224                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2225                              <1> 
  2226                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2227                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2228                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2229                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2230                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2231                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2232                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2233                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2234                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2235                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2236                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2237                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2238                              <1> 
  2239                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2240                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2241                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2242                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2243                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2244                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2245                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2246                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2247                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2248                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2249                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2250                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2251                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2252                              <1> 
  2253                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2254                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2255                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2256                              <1> 
  2257                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2258                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2259                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2260                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2261                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2262                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2263                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2264                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2265                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2266                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2267                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2268                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2269                              <1> 
  2270                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2271                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2272                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2273                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2274                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2275                              <1> 
  2276                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2277                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2278                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2279                              <1> INTA01		EQU	021H		; 8259 PORT
  2280                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2281                              <1> INTB01		EQU	0A1H		;
  2282                              <1> 
  2283                              <1> ;-------------------------------------------------------------------------------
  2284                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2285                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2286                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2287                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2288                              <1> ;-------------------------------------------------------------------------------
  2289                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2290                              <1> 
  2291                              <1> ;-------------------------------------------------------------------------------
  2292                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2293                              <1> 
  2294                              <1> ; 10/07/2022
  2295                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2296                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2297                              <1> ; (unix386.s <-- dsectrm2.s)
  2298                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2299                              <1> 
  2300                              <1> ; 10/12/2014
  2301                              <1> ;
  2302                              <1> ;int40h:
  2303                              <1> ;	pushf
  2304                              <1> ;	push 	cs
  2305                              <1> ;	;cli
  2306                              <1> ;	call 	DISKETTE_IO_1
  2307                              <1> ;	retn
  2308                              <1> 
  2309                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2310                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2311                              <1> ;
  2312                              <1> 
  2313                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2314                              <1> ; DISKETTE I/O
  2315                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2316                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2317                              <1> ; INPUT
  2318                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2319                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2320                              <1> ;		ON ALL DRIVES
  2321                              <1> ;------------------------------------------------------------------------------- 
  2322                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2323                              <1> ;-------------------------------------------------------------------------------
  2324                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2325                              <1> ;-------------------------------------------------------------------------------
  2326                              <1> ;
  2327                              <1> ;	REGISTERS FOR READ/WRITE
  2328                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2329                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2330                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2331                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2332                              <1> ;		320/360	320/360	    0-39
  2333                              <1> ;		320/360	1.2M	    0-39
  2334                              <1> ;		1.2M	1.2M	    0-79
  2335                              <1> ;		720K	720K	    0-79
  2336                              <1> ;		1.44M	1.44M	    0-79	
  2337                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2338                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2339                              <1> ;		320/360	320/360	     1-8/9
  2340                              <1> ;		320/360	1.2M	     1-8/9
  2341                              <1> ;		1.2M	1.2M	     1-15
  2342                              <1> ;		720K	720K	     1-9
  2343                              <1> ;		1.44M	1.44M	     1-18		
  2344                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2345                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2346                              <1> ;		320/360	320/360	        8/9
  2347                              <1> ;		320/360	1.2M	        8/9
  2348                              <1> ;		1.2M	1.2M		15
  2349                              <1> ;		720K	720K		9
  2350                              <1> ;		1.44M	1.44M		18
  2351                              <1> ;
  2352                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2353                              <1> ;
  2354                              <1> ;-------------------------------------------------------------------------------
  2355                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2356                              <1> ;	AH = STATUS OF OPERATION
  2357                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2358                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2359                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2360                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2361                              <1> ;	FOR READ/WRITE/VERIFY
  2362                              <1> ;		DS,BX,DX,CX PRESERVED
  2363                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2364                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2365                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2366                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2367                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2368                              <1> ;-------------------------------------------------------------------------------
  2369                              <1> ;
  2370                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2371                              <1> ;
  2372                              <1> ;   -----------------------------------------------------------------
  2373                              <1> ;   |       |       |       |       |       |       |       |       |
  2374                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2375                              <1> ;   |       |       |       |       |       |       |       |       |
  2376                              <1> ;   -----------------------------------------------------------------
  2377                              <1> ;	|	|	|	|	|	|	|	|
  2378                              <1> ;	|	|	|	|	|	-----------------
  2379                              <1> ;	|	|	|	|	|		|
  2380                              <1> ;	|	|	|	|    RESERVED		|
  2381                              <1> ;	|	|	|	|		  PRESENT STATE
  2382                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2383                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2384                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2385                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2386                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2387                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2388                              <1> ;	|	|	|	|	110: RESERVED
  2389                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2390                              <1> ;	|	|	|	|
  2391                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2392                              <1> ;	|	|	|
  2393                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2394                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2395                              <1> ;	|	|
  2396                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2397                              <1> ;
  2398                              <1> ;						00: 500 KBS
  2399                              <1> ;						01: 300 KBS
  2400                              <1> ;						10: 250 KBS
  2401                              <1> ;						11: RESERVED
  2402                              <1> ;
  2403                              <1> ;
  2404                              <1> 
  2405                              <1> struc MD
  2406 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2407 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2408 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2409 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2410 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2411 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2412 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2413 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2414 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2415 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2416 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2417 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2418 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2419                              <1> endstruc
  2420                              <1> 
  2421                              <1> BIT7OFF	EQU	7FH
  2422                              <1> BIT7ON	EQU	80H
  2423                              <1> 
  2424                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2425                              <1> ;		Function in AL
  2426                              <1> ;			0 = reset
  2427                              <1> ;			1 = read
  2428                              <1> ;			2 = write
  2429                              <1> ;		Disk drive number in DL
  2430                              <1> ;			0 & 1 = floppy disks	
  2431                              <1> ;			80h .. 83h = hard disks
  2432                              <1> ;		Sector address (LBA) in ECX
  2433                              <1> ;		Buffer address in EBX
  2434                              <1> ;		R/W sector count is (always) 1
  2435                              <1> ;
  2436                              <1> ;		Return:
  2437                              <1> ;			Status in AH (>0 = error code)
  2438                              <1> ;			if CF = 1 -> error code in AH
  2439                              <1> ;			if CF = 0 -> successful
  2440                              <1> ;			AL = undefined
  2441                              <1> ;
  2442                              <1> ;		Modified registers: (only) EAX
  2443                              <1> 
  2444                              <1> ; 11/07/2022
  2445                              <1> ;;int13h: ; 16/02/2015
  2446                              <1> ;; 16/02/2015 - 21/02/2015
  2447                              <1> ;int40h:
  2448                              <1> ;	pushfd
  2449                              <1> ;	push 	cs
  2450                              <1> ;	call 	DISKETTE_IO_1
  2451                              <1> ;	retn	
  2452                              <1> 
  2453                              <1> DISKETTE_IO_1:
  2454                              <1> 
  2455                              <1> 	;sti				; INTERRUPTS BACK ON
  2456                              <1> 	; 11/07/2022
  2457                              <1> 	; save registers
  2458 0000172C 55                  <1> 	push	ebp			; ANY
  2459                              <1> 
  2460                              <1> 	; 11/07/2022
  2461                              <1> 	;push	edi			; ANY
  2462                              <1> 	;push	edx			; DRIVE NUMBER (DL)
  2463                              <1> 	;push	ebx			; BUFFER ADDRESS
  2464                              <1> 	;push	ecx			; SECTOR ADDRESS (LBA)
  2465                              <1> 	;push	esi			; ANY
  2466                              <1> 
  2467                              <1> 	; 11/07/2022
  2468 0000172D 89DD                <1> 	mov	ebp, ebx ; buffer address
  2469 0000172F C605[AC680000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS
  2470 00001736 0FB6FA              <1> 	movzx	edi, dl ; drive number (0 or 1)
  2471                              <1> 	
  2472 00001739 08C0                <1> 	or	al, al			; RESET ?
  2473 0000173B 7507                <1> 	jnz	short DISKETTE_RW_1	; NO
  2474                              <1> 
  2475 0000173D E84F010000          <1> 	call	DSK_RESET
  2476                              <1> 
  2477 00001742 EB37                <1> 	jmp	short DISKETTE_RW_2	
  2478                              <1> 
  2479                              <1> DISKETTE_RW_1:
  2480                              <1> 	; 12/07/2022
  2481                              <1> 	; 11/07/2022
  2482                              <1> 	; ecx = sector address (LBA, < 2880)
  2483                              <1> 	; ebp = buffer address
  2484                              <1> 	; edi = drive number (0 or 1)
  2485                              <1> 	;  al = function (read = 1 or write = 2)
  2486                              <1> 
  2487 00001744 88C2                <1> 	mov	dl, al ; *
  2488                              <1> convert_to_chs:
  2489                              <1> 	;;;
  2490 00001746 B004                <1> 	mov	al, 4 ; MD.SEC_TRK ; sector per track (drv.spt)
  2491 00001748 E8F0050000          <1> 	call	GET_PARM
  2492                              <1> 	; 12/07/2022
  2493 0000174D 88E6                <1> 	mov	dh, ah ; spt
  2494 0000174F 89C8                <1> 	mov	eax, ecx ; sector address (LBA) 
  2495 00001751 F6F6                <1> 	div	dh  ; AX/DH
  2496 00001753 88E1                <1> 	mov	cl, ah ; sector number - 1
  2497 00001755 FEC1                <1> 	inc	cl  ; sector number (1 based)
  2498 00001757 28ED                <1> 	sub	ch, ch ; head = 0 
  2499                              <1> 	; heads = 2
  2500 00001759 D0E8                <1> 	shr	al, 1 ; al = al/2
  2501 0000175B 80D500              <1> 	adc	ch, 0 ; head = 1 or head = 0
  2502 0000175E C1E110              <1> 	shl	ecx, 16
  2503 00001761 88C1                <1> 	mov	cl, al ; track (cylinder)
  2504 00001763 88D5                <1> 	mov	ch, dl ; function number 
  2505 00001765 89CE                <1> 	mov	esi, ecx ; byte 0 = track, byte 1 = function
  2506                              <1> 			 ; byte 2 = sector, byte 3 = head
  2507 00001767 C1C610              <1> 	rol	esi, 16
  2508                              <1> 			 ; byte 0 = sector, byte 1 = head
  2509                              <1> 			 ; byte 2 = track, byte 3 = function		
  2510                              <1> 	;;; 
  2511 0000176A 80FA02              <1> 	cmp	dl, 2 ; *
  2512 0000176D 7407                <1> 	je	short DISKETTE_W
  2513                              <1> DISKETTE_R:	
  2514                              <1> 	; dl = 1 ; *
  2515 0000176F E809000000          <1> 	call	DSK_READ
  2516 00001774 EB05                <1> 	jmp	short DISKETTE_RW_2
  2517                              <1> DISKETTE_W:
  2518 00001776 E80F000000          <1> 	call	DSK_WRITE
  2519                              <1> DISKETTE_RW_2:
  2520                              <1> 	; 11/07/2022
  2521                              <1> 	; Restore registers
  2522                              <1> 	;pop	esi
  2523                              <1> 	;pop	ecx
  2524                              <1> 	;pop	ebx
  2525                              <1> 	;pop	edx
  2526                              <1> 	;pop	edi
  2527                              <1> 
  2528                              <1> 	; 11/07/2022
  2529 0000177B 5D                  <1> 	pop	ebp
  2530 0000177C C3                  <1> 	retn
  2531                              <1> 
  2532                              <1> ;-------------------------------------------------------------------------------
  2533                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2534                              <1> ;	DISKETTE READ.
  2535                              <1> ;
  2536                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2537                              <1> ;		SI-HI	: HEAD #
  2538                              <1> ;		SI-LOW	: # OF SECTORS
  2539                              <1> ;		ES	: BUFFER SEGMENT
  2540                              <1> ;		[BP]	: SECTOR #
  2541                              <1> ;		[BP+1]	: TRACK #
  2542                              <1> ;		[BP+2]	: BUFFER OFFSET
  2543                              <1> ;
  2544                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2545                              <1> ;-------------------------------------------------------------------------------
  2546                              <1> 
  2547                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2548                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2549                              <1> 
  2550                              <1> DSK_READ:
  2551 0000177D 8025[AA680000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2552 00001784 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2553                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2554                              <1> 	;retn
  2555 00001788 EB0B                <1> 	jmp	short RD_WR_VF
  2556                              <1> 
  2557                              <1> ;-------------------------------------------------------------------------------
  2558                              <1> ; DISK_WRITE	(AH = 02H)
  2559                              <1> ;	DISKETTE WRITE.
  2560                              <1> ;
  2561                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2562                              <1> ;		SI-HI	: HEAD #
  2563                              <1> ;		SI-LOW	: # OF SECTORS
  2564                              <1> ;		ES	: BUFFER SEGMENT
  2565                              <1> ;		[BP]	: SECTOR #
  2566                              <1> ;		[BP+1]	: TRACK #
  2567                              <1> ;		[BP+2]	: BUFFER OFFSET
  2568                              <1> ;
  2569                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2570                              <1> ;-------------------------------------------------------------------------------
  2571                              <1> 
  2572                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2573                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2574                              <1> 
  2575                              <1> DSK_WRITE:
  2576 0000178A 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2577 0000178E 800D[AA680000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2578                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2579                              <1> 	;;retn
  2580                              <1> 	;jmp	short RD_WR_VF
  2581                              <1> 
  2582                              <1> ;-------------------------------------------------------------------------------
  2583                              <1> ; RD_WR_VF
  2584                              <1> ;	COMMON READ, WRITE
  2585                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2586                              <1> ;
  2587                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2588                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2589                              <1> ;
  2590                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2591                              <1> ;-------------------------------------------------------------------------------
  2592                              <1> 
  2593                              <1> RD_WR_VF:
  2594                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2595 00001795 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2596 00001796 E8CD010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2597 0000179B E82F020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2598 000017A0 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2599                              <1> DO_AGAIN:
  2600 000017A1 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2601 000017A2 E869020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2602 000017A7 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2603                              <1> 	; 24/12/2021
  2604 000017A8 7305                <1> 	jnc	short RWV
  2605 000017AA E9B8000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2606                              <1> RWV:
  2607 000017AF 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2608 000017B0 8AB7[B7680000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2609 000017B6 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2610 000017B9 E876050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2611                              <1> 	; 20/02/2015
  2612 000017BE 7445                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2613 000017C0 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2614 000017C2 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2615 000017C4 F687[B7680000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2616 000017CB 740F                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2617                              <1> 	;mov	al, 2			; CHANGE TO 1.2M
  2618                              <1> 	; 12/07/2022
  2619 000017CD FEC0                <1> 	inc	al  ; al = 2
  2620 000017CF EB0B                <1> 	jmp	short RWV_2
  2621                              <1> RWV_1:
  2622                              <1> 	; 12/07/2022
  2623                              <1> 	;jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2624 000017D1 F687[B7680000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2625 000017D8 7502                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2626 000017DA B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2627                              <1> 	; 12/07/2022
  2628                              <1> 	;jmp	short RWV_3
  2629                              <1> RWV_2:
  2630                              <1> 	; 12/07/2022
  2631                              <1> 	;or	al, al			; TEST FOR NO DRIVE
  2632                              <1> 	;jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2633                              <1> RWV_3:
  2634                              <1> 	; 12/07/2022
  2635                              <1> 	;mov	dl, al	; 11/07/2022
  2636 000017DC E823010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2637 000017E1 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2638                              <1> 
  2639                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2640                              <1> 
  2641 000017E3 57                  <1> 	push	edi			; SAVE DRIVE #
  2642                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2643 000017E4 BB[CC620000]        <1> 	mov	ebx, DR_TYPE
  2644                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2645 000017E9 B106                <1> 	mov	cl, DR_CNT
  2646                              <1> RWV_DR_SEARCH:
  2647                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2648 000017EB 8A23                <1> 	mov	ah, [ebx]
  2649 000017ED 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2650 000017F0 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2651                              <1> 	; 12/07/2022
  2652                              <1> 	;cmp	dl, ah ; 11/07/2022
  2653 000017F2 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2654                              <1> RWV_DR_FND:
  2655                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2656 000017F4 43                  <1> 	inc	ebx
  2657 000017F5 8B3B                <1> 	mov	edi, [ebx]
  2658 000017F7 4B                  <1> 	dec	ebx
  2659                              <1> RWV_MD_SEARH:
  2660 000017F8 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2661 000017FB 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2662                              <1> RWV_NXT_MD:
  2663 000017FD 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2664                              <1> 	;loop	RWV_DR_SEARCH
  2665 00001800 FEC9                <1> 	dec	cl
  2666 00001802 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2667 00001804 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2668                              <1> 
  2669                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2670                              <1> 
  2671                              <1> RWV_ASSUME:
  2672 00001805 BB[EA620000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2673 0000180A F687[B7680000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2674 00001811 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2675 00001813 BB[04630000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2676 00001818 EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2677                              <1> 
  2678                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2679                              <1> 	 			
  2680                              <1> RWV_MD_FND:
  2681 0000181A 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2682 0000181C 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2683                              <1> 	
  2684                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2685                              <1> 
  2686                              <1> RWV_MD_FND1:
  2687 0000181D E828010000          <1> 	call	SEND_SPEC_MD
  2688 00001822 E855020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2689 00001827 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2690 00001829 E830020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2691                              <1> RWV_DBL:
  2692 0000182E 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2693 0000182F E85E040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2694 00001834 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2695 00001835 7223                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2696                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2697                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2698                              <1> 	; 08/07/2022
  2699 00001837 8B0424              <1> 	mov	eax, [esp]
  2700 0000183A 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2701 0000183B E84F020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2702 00001840 5B                  <1> 	pop	ebx
  2703 00001841 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2704 00001842 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2705 00001844 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2706 00001845 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2707 00001846 E8A1020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2708 0000184B 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2709 0000184C 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2710 0000184E E8CA020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2711 00001853 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2712 00001855 E811030000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2713                              <1> CHK_RET:
  2714 0000185A E8B0030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2715 0000185F 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2716 00001860 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2717 00001862 E93AFFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2718                              <1> RWV_END:
  2719 00001867 E85B030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2720 0000186C E8EC030000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2721                              <1> RWV_BAC:
  2722                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2723                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2724                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2725                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2726                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2727                              <1> 	;;retn
  2728                              <1> 	;jmp	SETUP_END
  2729                              <1> 
  2730                              <1> ;-------------------------------------------------------------------------------
  2731                              <1> ; SETUP_END
  2732                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2733                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2734                              <1> ;
  2735                              <1> ; ON EXIT:
  2736                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2737                              <1> ;-------------------------------------------------------------------------------
  2738                              <1> SETUP_END:
  2739                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2740                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2741                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2742 00001871 50                  <1> 	push	eax ; 24/12/2021
  2743 00001872 B002                <1> 	mov	al, 2 ; 08/07/2022
  2744 00001874 E8C4040000          <1> 	call	GET_PARM
  2745 00001879 8825[AB680000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2746                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2747 0000187F 58                  <1> 	pop	eax ; 24/12/2021
  2748 00001880 8A25[AC680000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2749 00001886 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2750 00001888 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2751 0000188A 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2752                              <1> ;NUN_ERR: 
  2753 0000188C 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2754 0000188F F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2755                              <1> NUN_ERR:
  2756 00001890 C3                  <1> 	retn
  2757                              <1> 
  2758                              <1> ;-------------------------------------------------------------------------------
  2759                              <1> ; DISK_RESET	(AH = 00H)	
  2760                              <1> ;		RESET THE DISKETTE SYSTEM.
  2761                              <1> ;
  2762                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2763                              <1> ;-------------------------------------------------------------------------------
  2764                              <1> DSK_RESET:
  2765                              <1> 	; 12/07/2022
  2766                              <1> 	; 11/07/2022
  2767                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2768 00001891 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2769 00001895 FA                  <1> 	cli				; NO INTERRUPTS
  2770 00001896 A0[AA680000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2771 0000189B 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2772 0000189D C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2773                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2774 000018A0 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2775 000018A2 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2776 000018A3 C605[A9680000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2777                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2778                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2779                              <1> 					;      PULSE WIDTH)
  2780                              <1> 	; 19/12/2014
  2781                              <1> 	NEWIODELAY
  2175 000018AA E6EB                <2>  out 0EBh,al
  2782                              <1> 
  2783                              <1> 	; 17/12/2014 
  2784                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2785 000018AC B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2786                              <1> wdw1:
  2787                              <1> 	NEWIODELAY   ; 27/02/2015
  2175 000018B1 E6EB                <2>  out 0EBh,al
  2788 000018B3 E2FC                <1> 	loop	wdw1
  2789                              <1> 	;
  2790 000018B5 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2791 000018B7 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2792                              <1> 	; 16/12/2014
  2793                              <1> 	IODELAY
  2170 000018B8 EB00                <2>  jmp short $+2
  2171 000018BA EB00                <2>  jmp short $+2
  2794                              <1> 	;
  2795                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2796 000018BC E877060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2797 000018C1 7238                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2798                              <1> 	;mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2799                              <1> 	; 12/07/2022
  2800                              <1> 	;xor	ecx, ecx
  2801 000018C3 30ED                <1> 	xor	ch, ch
  2802 000018C5 B1C0                <1> 	mov	cl, 11000000b
  2803                              <1> NXT_DRV:
  2804                              <1> 	; 24/12/2021
  2805 000018C7 51                  <1> 	push	ecx			; SAVE FOR CALL
  2806 000018C8 B8[FA180000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2807 000018CD 50                  <1> 	push	eax			;
  2808 000018CE B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2809 000018D0 E859050000          <1> 	call	NEC_OUTPUT
  2810 000018D5 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2811 000018D6 E88C060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2812                              <1> 	; 24/12/2021
  2813 000018DB 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2814 000018DC 721D                <1> 	jc	short DR_ERR		; ERROR RETURN
  2815 000018DE 3A0D[AD680000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2816 000018E4 7515                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2817 000018E6 FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2818 000018E8 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2819 000018EB 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2820                              <1> 	;
  2821 000018ED E82F000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2822                              <1> RESBAC:
  2823 000018F2 E87AFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2824                              <1> 	
  2825                              <1> 	; 11/07/2022
  2826                              <1> 	; CF = 1 -> error (error code in AH)
  2827                              <1> 	; CF = 0 -> OK
  2828                              <1> 	
  2829                              <1> 	;; 24/12/2021
  2830                              <1> 	;mov	ebx, esi		; GET SAVED AL TO BL
  2831                              <1> 	;; 11/07/2022
  2832                              <1> 	;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 
  2833                              <1> 	;rol	ebx, 8
  2834                              <1> 	; bl = function (reset = 0)
  2835                              <1> 	;
  2836                              <1> 	;mov	al, bl			; PUT BACK FOR RETURN
  2837                              <1> 	
  2838                              <1> 	; 11/07/2022  
  2839 000018F7 B000                <1> 	mov	al, 0	; (reset function = 0)
  2840                              <1> 
  2841 000018F9 C3                  <1> 	retn
  2842                              <1> 
  2843                              <1> DR_POP_ERR:
  2844                              <1> 	; 24/12/2021
  2845 000018FA 59                  <1> 	pop	ecx			; CLEAR STACK
  2846                              <1> DR_ERR:
  2847 000018FB 800D[AC680000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2848 00001902 EBEE                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2849                              <1> 
  2850                              <1> ;-------------------------------------------------------------------------------
  2851                              <1> ; FNC_ERR
  2852                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2853                              <1> ;	SET BAD COMMAND IN STATUS.
  2854                              <1> ;
  2855                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2856                              <1> ;-------------------------------------------------------------------------------
  2857                              <1> 
  2858                              <1> 	; 11/07/2022 - not needed (because diskio is used by kernel only)
  2859                              <1> 	
  2860                              <1> ;FNC_ERR:				; INVALID FUNCTION REQUEST
  2861                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2862                              <1> ;	; 24/12/2021
  2863                              <1> ;	mov	eax, esi		; RESTORE AL
  2864                              <1> ;	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2865                              <1> ;	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2866                              <1> ;	stc				; SET CARRY INDICATING ERROR
  2867                              <1> ;	retn
  2868                              <1> 
  2869                              <1> ;----------------------------------------------------------------
  2870                              <1> ; DR_TYPE_CHECK							:
  2871                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2872                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2873                              <1> ; ON ENTRY:							:
  2874                              <1> ;	AL = DRIVE TYPE						:
  2875                              <1> ; ON EXIT:							:
  2876                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2877                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2878                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2879                              <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 			:
  2880                              <1> ;----------------------------------------------------------------
  2881                              <1> DR_TYPE_CHECK:
  2882                              <1> 	; 12/07/2022
  2883                              <1> 	; 11/07/2022
  2884                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2885                              <1> 	; 24/12/2021
  2886                              <1> 	;push	eax ; 11/07/2022
  2887                              <1> 	;push	ecx ; 08/07/2022
  2888                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2889 00001904 BB[CC620000]        <1> 	mov	ebx, DR_TYPE
  2890                              <1> 	;;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2891                              <1> 	;mov	cl, DR_CNT
  2892 00001909 B406                <1> 	mov	ah, DR_CNT ; 11/07/2022
  2893                              <1> TYPE_CHK:	
  2894                              <1> 	;;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2895                              <1> 	;mov	ah, [ebx]
  2896                              <1> 	;cmp	al, ah			; DRIVE TYPE MATCH?
  2897 0000190B 3A03                <1> 	cmp	al, [ebx] ; 11/07/2022
  2898 0000190D 740E                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2899                              <1> 	; 16/02/2015 (32 bit address modification)
  2900 0000190F 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2901                              <1> 	;loop	TYPE_CHK
  2902                              <1> 	;dec	cl
  2903 00001912 FECC                <1> 	dec	ah ; 11/07/2022
  2904 00001914 75F5                <1> 	jnz	short TYPE_CHK
  2905                              <1> 	;
  2906 00001916 BB[2B630000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2907                              <1> 					; Default for GET_PARM (11/12/2014)
  2908                              <1> 	;
  2909 0000191B F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2910                              <1> 	;jmp	short TYPE_RTN
  2911                              <1> 	; 12/07/2022
  2912 0000191C C3                  <1> 	retn
  2913                              <1> DR_TYPE_VALID:
  2914                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2915 0000191D 43                  <1> 	inc	ebx
  2916 0000191E 8B1B                <1> 	mov	ebx, [ebx]
  2917                              <1> TYPE_RTN:
  2918                              <1> 	;pop	ecx ; 08/07/2022
  2919                              <1> 	; 24/12/2021
  2920                              <1> 	;pop	eax ; 11/07/2022
  2921 00001920 C3                  <1> 	retn
  2922                              <1> 		
  2923                              <1> ;----------------------------------------------------------------
  2924                              <1> ; SEND_SPEC							:
  2925                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2926                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2927                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2928                              <1> ; ON EXIT:	NONE						:
  2929                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2930                              <1> ;----------------------------------------------------------------
  2931                              <1> SEND_SPEC:
  2932                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2933 00001921 50                  <1> 	push	eax			; SAVE EAX
  2934 00001922 B8[48190000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2935 00001927 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2936 00001928 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2937 0000192A E8FF040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2938                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2939 0000192F 28C0                <1> 	sub	al, al ; 08/07/2022
  2940 00001931 E807040000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2941 00001936 E8F3040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2942                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2943 0000193B B001                <1> 	mov	al, 1 ; 08/07/2022
  2944 0000193D E8FB030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2945 00001942 E8E7040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2946 00001947 58                  <1> 	pop	eax			; POP ERROR RETURN
  2947                              <1> SPECBAC:
  2948 00001948 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2949 00001949 C3                  <1> 	retn
  2950                              <1> 
  2951                              <1> ;----------------------------------------------------------------
  2952                              <1> ; SEND_SPEC_MD							:
  2953                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2954                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (EBX)	:
  2955                              <1> ; ON ENTRY:	EBX = MEDIA/DRIVE PARAMETER TABLE		:
  2956                              <1> ; ON EXIT:	NONE						:
  2957                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022				:
  2958                              <1> ;----------------------------------------------------------------
  2959                              <1> SEND_SPEC_MD:
  2960                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2961                              <1> 	;push	eax ; 11/07/2022	; SAVE RATE DATA
  2962 0000194A B8[67190000]        <1> 	mov	eax, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2963 0000194F 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2964 00001950 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2965 00001952 E8D7040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2966 00001957 8A23                <1>         mov	ah, [ebx+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2967 00001959 E8D0040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2968 0000195E 8A6301              <1>         mov	ah, [ebx+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2969 00001961 E8C8040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2970 00001966 58                  <1> 	pop	eax			; POP ERROR RETURN
  2971                              <1> SPEC_ESBAC:
  2972                              <1> 	;pop	eax ; 11/07/2022	; RESTORE ORIGINAL EAX VALUE
  2973 00001967 C3                  <1> 	retn
  2974                              <1> 
  2975                              <1> ;-------------------------------------------------------------------------------
  2976                              <1> ; XLAT_NEW  
  2977                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  2978                              <1> ;	MODE TO NEW ARCHITECTURE.
  2979                              <1> ;
  2980                              <1> ; ON ENTRY:	EDI = DRIVE #
  2981                              <1> ;-------------------------------------------------------------------------------
  2982                              <1> XLAT_NEW:
  2983                              <1> 	; 11/07/2022
  2984                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2985                              <1> 	;cmp	edi, 1				; VALID DRIVE
  2986                              <1> 	;ja	short XN_OUT			; IF INVALID BACK
  2987                              <1> 	;
  2988 00001968 80BF[B7680000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  2989 0000196F 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  2990                              <1> 	;
  2991                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2992                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  2993                              <1> 	;or	cl, cl
  2994                              <1> 	;jz	short XN_0  ; 08/07/2022
  2995                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  2996                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2997                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  2998                              <1> ;XN_0:	
  2999                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3000                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3001                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  3002                              <1> XN_OUT:
  3003 00001971 C3                  <1> 	retn
  3004                              <1> DO_DET:
  3005                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  3006                              <1> 	;;retn
  3007                              <1> 	;jmp	DRIVE_DET
  3008                              <1> 
  3009                              <1> ;-------------------------------------------------------------------------------
  3010                              <1> ; DRIVE_DET
  3011                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  3012                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  3013                              <1> ; ON ENTRY:	EDI = DRIVE #
  3014                              <1> ;-------------------------------------------------------------------------------
  3015                              <1> DRIVE_DET:
  3016                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3017 00001972 E801040000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  3018 00001977 E86A050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  3019 0000197C 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  3020 0000197E B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  3021 00001980 E8E2040000          <1> 	call	SEEK
  3022 00001985 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  3023 00001987 B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  3024                              <1> SK_GIN:
  3025 00001989 FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  3026                              <1> 	;push	cx		
  3027                              <1> 	; 24/12/2021
  3028 0000198B 51                  <1> 	push	ecx			; SAVE TRACK
  3029 0000198C E8D6040000          <1> 	call	SEEK
  3030 00001991 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  3031 00001993 B8[CD190000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  3032 00001998 50                  <1> 	push	eax
  3033 00001999 B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  3034 0000199B E88E040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3035                              <1> 	; 08/07/2022
  3036 000019A0 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  3037 000019A2 88C4                <1> 	mov	ah, al			; AH = DRIVE
  3038 000019A4 E885040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3039 000019A9 E8B9050000          <1> 	call	RESULTS			; GO GET STATUS
  3040 000019AE 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3041                              <1> 	;pop	cx			; RESTORE TRACK
  3042                              <1> 	; 24/12/2021
  3043 000019AF 59                  <1> 	pop	ecx
  3044 000019B0 F605[AD680000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  3045 000019B7 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  3046 000019B9 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  3047 000019BB 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  3048                              <1> 
  3049                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  3050                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  3051                              <1> 
  3052 000019BD 808F[B7680000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  3053 000019C4 C3                  <1> 	retn				; ALL INFORMATION SET
  3054                              <1> IS_80:
  3055 000019C5 808F[B7680000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3056                              <1> DD_BAC:
  3057 000019CC C3                  <1> 	retn
  3058                              <1> POP_BAC:
  3059                              <1> 	;pop	cx			; THROW AWAY
  3060                              <1> 	; 24/12/2021
  3061 000019CD 59                  <1> 	pop	ecx
  3062 000019CE C3                  <1> 	retn
  3063                              <1> 
  3064                              <1> ;-------------------------------------------------------------------------------
  3065                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3066                              <1> ;-------------------------------------------------------------------------------
  3067                              <1> SETUP_STATE:
  3068                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3069 000019CF F687[B7680000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3070 000019D6 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3071 000019D8 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3072 000019DC F687[B7680000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3073 000019E3 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3074 000019E5 F687[B7680000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3075 000019EC 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3076 000019EE 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3077                              <1> AX_SET:	
  3078 000019F2 80A7[B7680000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3079 000019F9 08A7[B7680000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3080 000019FF 8025[B4680000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3081 00001A06 C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3082 00001A09 0805[B4680000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3083                              <1> J1C:	
  3084 00001A0F C3                  <1> 	retn
  3085                              <1> 
  3086                              <1> ;-------------------------------------------------------------------------------
  3087                              <1> ; MED_CHANGE	
  3088                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3089                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3090                              <1> ;
  3091                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3092                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3093                              <1> ;-------------------------------------------------------------------------------
  3094                              <1> MED_CHANGE:
  3095                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3096 00001A10 E8AA050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3097 00001A15 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3098 00001A17 80A7[B7680000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3099                              <1> 
  3100                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3101                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3102                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3103                              <1> 
  3104 00001A1E 89F9                <1> 	mov	ecx, edi		; CL = DRIVE #
  3105 00001A20 B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3106 00001A22 D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3107 00001A24 F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3108 00001A26 FA                  <1> 	cli				; NO INTERRUPTS
  3109 00001A27 2005[AA680000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3110 00001A2D FB                  <1> 	sti				; INTERRUPTS ENABLED
  3111 00001A2E E845030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3112                              <1> 
  3113                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3114                              <1> 
  3115 00001A33 E859FEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3116 00001A38 B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3117 00001A3A E828040000          <1> 	call	SEEK			; ISSUE SEEK
  3118 00001A3F 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3119 00001A41 E821040000          <1> 	call	SEEK			; ISSUE SEEK
  3120 00001A46 C605[AC680000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3121                              <1> OK1:
  3122 00001A4D E86D050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3123 00001A52 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3124                              <1> OK4:
  3125 00001A54 C605[AC680000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3126                              <1> OK2:		
  3127 00001A5B F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3128 00001A5C C3                  <1> 	retn
  3129                              <1> MC_OUT:
  3130                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3131 00001A5D C3                  <1> 	retn
  3132                              <1> 
  3133                              <1> ;-------------------------------------------------------------------------------
  3134                              <1> ; SEND_RATE
  3135                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3136                              <1> ; ON ENTRY:	EDI = DRIVE #
  3137                              <1> ; ON EXIT:	NONE
  3138                              <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022
  3139                              <1> ;-------------------------------------------------------------------------------
  3140                              <1> SEND_RATE:
  3141                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5
  3142                              <1> 	;push	ax			; SAVE REG.
  3143                              <1> 	; 24/12/2021
  3144                              <1> 	;push	eax ; 11/07/2022
  3145 00001A5E 8025[B4680000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3146 00001A65 8A87[B7680000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3147 00001A6B 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3148 00001A6D 0805[B4680000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3149 00001A73 C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3150 00001A76 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3151 00001A7A EE                  <1> 	out	dx, al
  3152                              <1> 	;pop	ax			; RESTORE REG.
  3153                              <1> 	; 24/12/2021
  3154                              <1> 	;pop	eax ; 11/07/2022
  3155 00001A7B C3                  <1> 	retn
  3156                              <1> 
  3157                              <1> ;-------------------------------------------------------------------------------
  3158                              <1> ; CHK_LASTRATE
  3159                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3160                              <1> ; ON ENTRY:
  3161                              <1> ;	EDI = DRIVE #
  3162                              <1> ; ON EXIT:
  3163                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3164                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3165                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022
  3166                              <1> ;-------------------------------------------------------------------------------
  3167                              <1> CHK_LASTRATE:
  3168                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3169                              <1> 	;push	ax			; SAVE REG.
  3170                              <1> 	; 24/12/2021
  3171                              <1> 	;push	eax ; 11/07/2022
  3172 00001A7C 8A25[B4680000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3173                              <1> 					; GET LAST DATA RATE SELECTED
  3174 00001A82 8A87[B7680000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3175 00001A88 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3176 00001A8C 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3177                              <1> 					; ZF = 1 RATE IS THE SAME
  3178                              <1> 	;pop	ax			; RESTORE REG.
  3179                              <1> 	; 24/12/2021
  3180                              <1> 	;pop	eax ; 11/07/2022
  3181 00001A8E C3                  <1> 	retn
  3182                              <1> 
  3183                              <1> ;-------------------------------------------------------------------------------
  3184                              <1> ; DMA_SETUP
  3185                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3186                              <1> ;
  3187                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3188                              <1> ;
  3189                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3190                              <1> ;-------------------------------------------------------------------------------
  3191                              <1> 
  3192                              <1> ; SI = Head #, # of Sectors or DASD Type
  3193                              <1> 
  3194                              <1> ; 22/08/2015
  3195                              <1> ; 08/02/2015 - Protected Mode Modification
  3196                              <1> ; 06/02/2015 - 07/02/2015
  3197                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3198                              <1> ; (DMA Addres = Physical Address)
  3199                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3200                              <1> ;
  3201                              <1> ; 04/02/2016 (clc)
  3202                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3203                              <1> ; 16/12/2014 (IODELAY)
  3204                              <1> 
  3205                              <1> DMA_SETUP:
  3206                              <1> 	; 11/07/2022
  3207                              <1> 	;	ebp = buffer address
  3208                              <1> 	
  3209                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3210                              <1> 	;; 20/02/2015
  3211                              <1> 	;mov	edx, [ebp+4] ; 11/07/2022 ; Buffer address
  3212                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3213                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3214                              <1> 	;jnz	short dma_bnd_err_stc
  3215                              <1> 	; 24/12/2021
  3216 00001A8F 50                  <1> 	push	eax			; DMA command
  3217                              <1> 	;push	edx ; 11/07/2022	; *
  3218                              <1> 	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3219 00001A90 B003                <1> 	mov	al, 3 ; 08/07/2022
  3220 00001A92 E8A6020000          <1> 	call	GET_PARM		; 
  3221 00001A97 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3222                              <1> 	;mov	ax, si			; Sector count
  3223                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3224                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3225                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3226                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3227                              <1> 	; 08/07/2022
  3228                              <1> 	; 24/12/2021
  3229                              <1> 	;mov	edx, esi
  3230 00001A99 29C0                <1> 	sub	eax, eax
  3231                              <1> 	;mov	ah, dl
  3232                              <1> 	;shr	eax, 1
  3233 00001A9B B080                <1> 	mov	al, 128
  3234 00001A9D D3E0                <1> 	shl	eax, cl
  3235                              <1> 	;
  3236 00001A9F 48                  <1> 	dec	eax			; -1 FOR DMA VALUE
  3237 00001AA0 89C1                <1> 	mov	ecx, eax
  3238                              <1> 	;pop	edx ; 11/07/2022	; *
  3239                              <1> 	; 24/12/2021
  3240 00001AA2 58                  <1> 	pop	eax
  3241                              <1> 	; 08/07/2022
  3242                              <1> 	;cmp	al, 42h
  3243                              <1>         ;jne	short NOT_VERF
  3244                              <1> 	;mov	edx, 0FF0000h
  3245                              <1> 	;jmp	short J33
  3246                              <1> ;NOT_VERF:
  3247                              <1> 	; 11/07/2022
  3248 00001AA3 89EA                <1> 	mov	edx, ebp
  3249                              <1> 	;
  3250 00001AA5 6601CA              <1> 	add	dx, cx			; check for (64K) overflow
  3251 00001AA8 723A                <1> 	jc	short dma_bnd_err
  3252                              <1> 	;
  3253                              <1> 	;sub	dx, cx ; 11/07/2022	; Restore start address
  3254                              <1> J33:
  3255                              <1> 	; 08/07/2022
  3256 00001AAA FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3257 00001AAB E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LA5T F/F
  3258                              <1> 	IODELAY				; WAIT FOR I/O
  2170 00001AAD EB00                <2>  jmp short $+2
  2171 00001AAF EB00                <2>  jmp short $+2
  3259 00001AB1 E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3260                              <1> 	;mov	eax, edx		; Buffer address
  3261                              <1> 	; 11/07/2022
  3262 00001AB3 89E8                <1> 	mov	eax, ebp ; buffer address
  3263 00001AB5 E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3264                              <1> 	IODELAY				; WAIT FOR I/O
  2170 00001AB7 EB00                <2>  jmp short $+2
  2171 00001AB9 EB00                <2>  jmp short $+2
  3265 00001ABB 88E0                <1> 	mov	al, ah
  3266 00001ABD E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3267 00001ABF C1E810              <1> 	shr	eax, 16
  3268                              <1> 	IODELAY				; I/O WAIT STATE
  2170 00001AC2 EB00                <2>  jmp short $+2
  2171 00001AC4 EB00                <2>  jmp short $+2
  3269 00001AC6 E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3270                              <1> 	IODELAY
  2170 00001AC8 EB00                <2>  jmp short $+2
  2171 00001ACA EB00                <2>  jmp short $+2
  3271                              <1> 	;mov	ax, cx			; Byte count - 1
  3272 00001ACC 88C8                <1> 	mov	al, cl
  3273 00001ACE E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3274                              <1> 	IODELAY				; WAIT FOR I/O
  2170 00001AD0 EB00                <2>  jmp short $+2
  2171 00001AD2 EB00                <2>  jmp short $+2
  3275                              <1> 	;mov	al, ah
  3276 00001AD4 88E8                <1> 	mov	al, ch
  3277 00001AD6 E605                <1> 	OUT	DMA+5, al		; HIGH BYTE OF COUNT
  3278                              <1> 	IODELAY
  2170 00001AD8 EB00                <2>  jmp short $+2
  2171 00001ADA EB00                <2>  jmp short $+2
  3279 00001ADC FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3280 00001ADD B002                <1> 	mov	al, 2			; MODE FOR 8237
  3281 00001ADF E60A                <1> 	OUT	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3282                              <1> 
  3283 00001AE1 F8                  <1> 	clc	; 04/02/2016
  3284 00001AE2 C3                  <1> 	retn
  3285                              <1> 
  3286                              <1> dma_bnd_err_stc:
  3287 00001AE3 F9                  <1> 	stc
  3288                              <1> dma_bnd_err:
  3289 00001AE4 C605[AC680000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3290 00001AEB C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3291                              <1> 
  3292                              <1> ;-------------------------------------------------------------------------------
  3293                              <1> ; NEC_INIT	
  3294                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3295                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3296                              <1> ;
  3297                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3298                              <1> ;
  3299                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3300                              <1> ;-------------------------------------------------------------------------------
  3301                              <1> NEC_INIT:
  3302                              <1> 	; 11/07/2022
  3303                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3304                              <1> 	;push	ax			; SAVE NEC COMMAND
  3305                              <1> 	; 24/12/2021
  3306 00001AEC 50                  <1> 	push	eax
  3307 00001AED E886020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3308                              <1> 
  3309                              <1> ;-----	DO THE SEEK OPERATION
  3310                              <1> 
  3311                              <1> 	;mov	ch, [ebp+1]		; CH = TRACK #
  3312                              <1> 	; 11/07/2022
  3313 00001AF2 89F1                <1> 	mov	ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector
  3314 00001AF4 C1E908              <1> 	shr	ecx, 8
  3315                              <1> 	; ch = track #	
  3316                              <1> 
  3317 00001AF7 E86B030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3318                              <1> 	;pop	ax			; RECOVER COMMAND
  3319                              <1> 	; 24/12/2021
  3320 00001AFC 58                  <1> 	pop	eax
  3321 00001AFD 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3322 00001AFF BB[1C1B0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3323 00001B04 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3324                              <1> 
  3325                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3326                              <1> 
  3327 00001B05 E824030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3328 00001B0A 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3329 00001B0C 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3330 00001B0E C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3331 00001B11 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3332 00001B14 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3333 00001B16 E813030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3334 00001B1B 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3335                              <1> ER_1:
  3336 00001B1C C3                  <1> 	retn
  3337                              <1> 
  3338                              <1> ;-------------------------------------------------------------------------------
  3339                              <1> ; RWV_COM
  3340                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3341                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3342                              <1> ;
  3343                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3344                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3345                              <1> ;-------------------------------------------------------------------------------
  3346                              <1> RWV_COM:
  3347                              <1> 	; 11/07/2022
  3348                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3349 00001B1D B8[6A1B0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3350 00001B22 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3351                              <1> 	;mov	ah, [ebp+1]		; OUTPUT TRACK #
  3352                              <1> 	; 11/07/2022
  3353 00001B23 89F0                <1> 	mov	eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track
  3354 00001B25 C1E808              <1> 	shr	eax, 8
  3355                              <1> 	; ah = track # 
  3356 00001B28 E801030000          <1> 	call	NEC_OUTPUT
  3357 00001B2D 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3358                              <1> 	; ah = head #
  3359 00001B2F E8FA020000          <1> 	call	NEC_OUTPUT
  3360                              <1>         ;mov	ah, [ebp]		; OUTPUT SECTOR #
  3361 00001B34 89F0                <1> 	mov	eax, esi
  3362 00001B36 88C4                <1> 	mov	ah, al
  3363                              <1>  	; ah = sector #
  3364 00001B38 E8F1020000          <1> 	CALL	NEC_OUTPUT
  3365                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3366 00001B3D B003                <1> 	mov	al, 3 ; 08/07/2022
  3367 00001B3F E8F9010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3368 00001B44 E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3369                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3370 00001B49 B004                <1> 	mov	al, 4 ; 08/07/2022
  3371 00001B4B E8ED010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3372 00001B50 E8D9020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3373 00001B55 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3374                              <1> _R15:
  3375 00001B58 E8D1020000          <1> 	call	NEC_OUTPUT
  3376                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3377 00001B5D B006                <1> 	mov	al, 6 ; 08/07/2022
  3378 00001B5F E8D9010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3379 00001B64 E8C5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3380 00001B69 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3381                              <1> ER_2:
  3382 00001B6A C3                  <1> 	retn
  3383                              <1> 
  3384                              <1> ;-------------------------------------------------------------------------------
  3385                              <1> ; NEC_TERM
  3386                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3387                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3388                              <1> ;
  3389                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3390                              <1> ;-------------------------------------------------------------------------------
  3391                              <1> 
  3392                              <1> NEC_TERM:
  3393                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3394                              <1> 
  3395                              <1> ;-----	LET THE OPERATION HAPPEN
  3396                              <1> 
  3397 00001B6B 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3398 00001B6C E8C7030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3399 00001B71 9C                  <1> 	pushfd	; 24/12/2021
  3400 00001B72 E8F0030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3401 00001B77 724B                <1> 	jc	short SET_END_POP
  3402 00001B79 9D                  <1> 	popfd	; 24/12/2021
  3403 00001B7A 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3404                              <1> 
  3405                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3406                              <1> 
  3407 00001B7C FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3408 00001B7D BE[AD680000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3409 00001B82 AC                  <1> 	lodsb				; GET ST0
  3410 00001B83 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3411 00001B85 7433                <1> 	jz	short SET_END
  3412 00001B87 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3413 00001B89 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3414                              <1> 
  3415                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3416                              <1> 
  3417 00001B8B AC                  <1> 	lodsb				; GET ST1
  3418 00001B8C D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3419 00001B8E B404                <1> 	mov	ah, RECORD_NOT_FND
  3420 00001B90 7222                <1> 	jc	short J19
  3421 00001B92 C0E002              <1> 	sal	al, 2
  3422 00001B95 B410                <1> 	mov	ah, BAD_CRC
  3423 00001B97 721B                <1> 	jc	short J19
  3424 00001B99 D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3425 00001B9B B408                <1> 	mov	ah, BAD_DMA
  3426 00001B9D 7215                <1> 	jc	short J19
  3427 00001B9F C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3428 00001BA2 B404                <1> 	mov	ah, RECORD_NOT_FND
  3429 00001BA4 720E                <1> 	jc	short J19
  3430 00001BA6 D0E0                <1> 	sal	al, 1
  3431 00001BA8 B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3432 00001BAA 7208                <1> 	jc	short J19
  3433 00001BAC D0E0                <1> 	sal	al, 1			; TEST MISSING ADDRESS MARK
  3434 00001BAE B402                <1> 	mov	ah, BAD_ADDR_MARK
  3435 00001BB0 7202                <1> 	jc	short J19
  3436                              <1> 
  3437                              <1> ;----- 	NEC MUST HAVE FAILED
  3438                              <1> J18:
  3439 00001BB2 B420                <1> 	mov	ah, BAD_NEC
  3440                              <1> J19:
  3441 00001BB4 0825[AC680000]      <1> 	or	[DSKETTE_STATUS], ah
  3442                              <1> SET_END:
  3443 00001BBA 803D[AC680000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3444 00001BC1 F5                  <1> 	cmc
  3445 00001BC2 5E                  <1> 	pop	esi
  3446 00001BC3 C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3447                              <1> 
  3448                              <1> SET_END_POP:
  3449 00001BC4 9D                  <1> 	popfd	; 24/12/2021
  3450 00001BC5 EBF3                <1> 	jmp	short SET_END
  3451                              <1> 
  3452                              <1> ;-------------------------------------------------------------------------------
  3453                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3454                              <1> ;-------------------------------------------------------------------------------
  3455                              <1> DSTATE:
  3456                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3457 00001BC7 803D[AC680000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3458 00001BCE 753E                <1> 	jne	short SETBAC		; IF ERROR JUMP
  3459 00001BD0 808F[B7680000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3460 00001BD7 F687[B7680000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3461 00001BDE 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3462 00001BE0 8A87[B7680000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3463 00001BE6 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3464 00001BE8 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3465 00001BEA 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3466                              <1> 
  3467                              <1> ;----- 	CHECK IF IT IS 1.44M
  3468                              <1> 
  3469 00001BEC E843010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3470                              <1> 	;;20/02/2015
  3471                              <1> 	;;jc	short M_12		; CMOS BAD
  3472 00001BF1 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3473 00001BF3 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3474 00001BF5 7410                <1> 	je	short M_12		; YES
  3475                              <1> M_720:
  3476 00001BF7 80A7[B7680000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3477 00001BFE 808F[B7680000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3478 00001C05 EB07                <1> 	jmp	short SETBAC		; BACK
  3479                              <1> M_12:	
  3480 00001C07 808F[B7680000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3481                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3482                              <1> SETBAC:
  3483 00001C0E C3                  <1> 	retn
  3484                              <1> 
  3485                              <1> ;-------------------------------------------------------------------------------
  3486                              <1> ; RETRY	
  3487                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3488                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3489                              <1> ;
  3490                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3491                              <1> ;-------------------------------------------------------------------------------
  3492                              <1> RETRY:
  3493                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3494 00001C0F 803D[AC680000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3495 00001C16 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3496 00001C18 803D[AC680000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3497 00001C1F 743B                <1> 	je	short NO_RETRY
  3498 00001C21 8AA7[B7680000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3499 00001C27 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3500 00001C2A 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3501 00001C2C 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3502 00001C2F 8A2D[B4680000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3503 00001C35 C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3504 00001C38 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3505 00001C3B 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3506 00001C3D 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3507                              <1> 
  3508                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3509                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3510                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3511                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3512                              <1> 
  3513 00001C3F 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3514 00001C42 D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3515 00001C44 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3516 00001C47 80A7[B7680000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3517                              <1> 					; RATE, DBL STEP OFF
  3518 00001C4E 08A7[B7680000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3519 00001C54 C605[AC680000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3520 00001C5B F9                  <1> 	stc				; SET CARRY FOR RETRY
  3521                              <1> NO_RETRY:	; 08/07/2022
  3522 00001C5C C3                  <1> 	retn				; RETRY RETURN
  3523                              <1> 
  3524                              <1> ;NO_RETRY:
  3525                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3526                              <1> 	;RETn				; NO RETRY RETURN
  3527                              <1> 
  3528                              <1> ;-------------------------------------------------------------------------------
  3529                              <1> ; NUM_TRANS
  3530                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3531                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3532                              <1> ;
  3533                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3534                              <1> ;		SI-HI  = HEAD
  3535                              <1> ;		[BP]   = START SECTOR
  3536                              <1> ;
  3537                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3538                              <1> ;-------------------------------------------------------------------------------
  3539                              <1> NUM_TRANS:
  3540                              <1> 	; 11/07/2022
  3541                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3542 00001C5D 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3543 00001C5F 803D[AC680000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3544                              <1> 	; 24/12/2021
  3545 00001C66 7529                <1> 	jne	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3546                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3547 00001C68 B004                <1> 	mov	al, 4 ; 08/07/2022
  3548 00001C6A E8CE000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3549                              <1> 	;mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3550 00001C6F A0[B2680000]        <1> 	mov	al, [NEC_STATUS+5]
  3551 00001C74 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3552 00001C76 88CB                <1> 	mov	bl, cl ; 11/07/2022 ; sector #
  3553 00001C78 3A2D[B1680000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3554 00001C7E 750D                <1> 	jne	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3555                              <1> 	; 11/07/2022
  3556                              <1> 	;mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3557                              <1> 	;cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3558                              <1> 	;jz	short SAME_TR		; IF SAME TRACK NO INCREASE
  3559 00001C80 C1E908              <1> 	shr	ecx, 8 ; byte 3 = track # --> byte 2
  3560 00001C83 3A2D[B0680000]      <1> 	cmp	ch, [NEC_STATUS+3]
  3561 00001C89 7404                <1> 	je	short SAME_TRK		
  3562                              <1> 	; 11/07/2022
  3563                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3564 00001C8B 00E0                <1> 	add	al, ah
  3565                              <1> DIF_HD:
  3566                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3567 00001C8D 00E0                <1> 	add	al, ah
  3568                              <1> SAME_TRK:
  3569                              <1> 	;sub	bl, [ebp]		; SUBTRACT START FROM END
  3570                              <1> 	;mov	al, bl			; TO AL
  3571 00001C8F 28D8                <1> 	sub	al, bl
  3572                              <1> NT_OUT:
  3573 00001C91 C3                  <1> 	retn
  3574                              <1> 
  3575                              <1> ;-------------------------------------------------------------------------------
  3576                              <1> ; SETUP_DBL
  3577                              <1> ;	CHECK DOUBLE STEP.
  3578                              <1> ;
  3579                              <1> ; ON ENTRY :	EDI = DRIVE #
  3580                              <1> ;
  3581                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3582                              <1> ;-------------------------------------------------------------------------------
  3583                              <1> SETUP_DBL:
  3584                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3585 00001C92 8AA7[B7680000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3586 00001C98 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3587 00001C9B 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3588                              <1> 
  3589                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3590                              <1> 
  3591 00001C9D C605[A9680000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3592 00001CA4 E8CF000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3593 00001CA9 B500                <1> 	mov	ch, 0			; LOAD TRACK 0
  3594 00001CAB E8B7010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3595 00001CB0 E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3596 00001CB5 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3597                              <1> 
  3598                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3599                              <1> 
  3600 00001CB7 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3601 00001CBB F687[B7680000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3602 00001CC2 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3603 00001CC4 B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3604                              <1> 
  3605                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3606                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3607                              <1> ;	THEN SET DOUBLE STEP ON.
  3608                              <1> 
  3609                              <1> CNT_OK:
  3610 00001CC6 C605[AB680000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3611                              <1> 	; 24/12/2021
  3612 00001CCD 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3613 00001CCE C605[AC680000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3614 00001CD5 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3615 00001CD7 D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3616 00001CD9 C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3617                              <1> 	; 24/12/2021
  3618 00001CDC 50                  <1> 	push	eax			; SAVE HEAD
  3619 00001CDD E885010000          <1> 	call	SEEK			; SEEK TO TRACK
  3620                              <1> 	; 24/12/2021
  3621 00001CE2 58                  <1> 	pop	eax			; RESTORE HEAD
  3622 00001CE3 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3623 00001CE5 E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3624 00001CEA 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3625 00001CEB 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3626 00001CF0 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3627                              <1> 	; 24/12/2021
  3628 00001CF1 59                  <1> 	pop	ecx			; RESTORE COUNT
  3629 00001CF2 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3630 00001CF4 FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3631 00001CF6 38CD                <1> 	cmp	ch, cl			; REACHED MAXIMUM YET
  3632 00001CF8 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3633                              <1> 
  3634                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3635                              <1> 
  3636                              <1> SD_ERR:	
  3637 00001CFA F9                  <1> 	stc				; SET CARRY FOR ERROR
  3638 00001CFB C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3639                              <1> 
  3640                              <1> DO_CHK:
  3641 00001CFC 8A0D[B0680000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3642 00001D02 888F[B9680000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3643 00001D08 D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3644 00001D0A 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3645 00001D0C 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3646 00001D0E 808F[B7680000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3647                              <1> NO_DBL:
  3648 00001D15 F8                  <1> 	clc				; CLEAR ERROR FLAG
  3649 00001D16 C3                  <1> 	retn
  3650                              <1> 
  3651                              <1> ;-------------------------------------------------------------------------------
  3652                              <1> ; READ_ID
  3653                              <1> ;	READ ID FUNCTION.
  3654                              <1> ;
  3655                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3656                              <1> ;
  3657                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3658                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3659                              <1> ;-------------------------------------------------------------------------------
  3660                              <1> READ_ID:
  3661                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3662 00001D17 B8[331D0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3663 00001D1C 50                  <1> 	push	eax
  3664 00001D1D B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3665 00001D1F E80A010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3666 00001D24 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3667 00001D26 88C4                <1> 	mov	ah, al
  3668 00001D28 E801010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3669 00001D2D E839FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3670 00001D32 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3671                              <1> ER_3:
  3672 00001D33 C3                  <1> 	retn
  3673                              <1> 
  3674                              <1> ;-------------------------------------------------------------------------------
  3675                              <1> ; CMOS_TYPE
  3676                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3677                              <1> ;
  3678                              <1> ; ON ENTRY:	EDI = DRIVE #
  3679                              <1> ;
  3680                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3681                              <1> ;-------------------------------------------------------------------------------
  3682                              <1> 
  3683                              <1> CMOS_TYPE: ; 11/12/2014
  3684                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3685 00001D34 8A87[4C630000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3686 00001D3A 20C0                <1> 	and 	al, al ; 18/12/2014
  3687 00001D3C C3                  <1> 	retn
  3688                              <1> 
  3689                              <1> ;-------------------------------------------------------------------------------
  3690                              <1> ; GET_PARM
  3691                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3692                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3693                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3694                              <1> ;	THE PARAMETER IN DL.
  3695                              <1> ;
  3696                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3697                              <1> ;
  3698                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3699                              <1> ;		AL DESTROYED
  3700                              <1> ;-------------------------------------------------------------------------------
  3701                              <1> GET_PARM:
  3702                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3703                              <1> 	;	 ENTRY:
  3704                              <1> 	;	     AL = INDEX
  3705                              <1> 	;	    EDI = DRIVE #
  3706                              <1> 	; 	 RETURN:
  3707                              <1> 	;	     AH = REQUESTED PARAMETER
  3708                              <1> 	;	     AL DESTROYED
  3709                              <1> 	
  3710                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3711                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3712                              <1> 	;push	esi ; 11/07/2022
  3713 00001D3D 53                  <1> 	push	ebx			; SAVE EBX	
  3714 00001D3E 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3715                              <1>    	; 17/12/2014
  3716                              <1> 	;mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3717                              <1> 	; 11/07/2022
  3718                              <1> 	;cmp	al, ah
  3719                              <1> 	;je	short gpndc
  3720                              <1> 
  3721                              <1> 	; 11/07/2022
  3722 00001D41 89F8                <1> 	mov	eax, edi
  3723 00001D43 3A05[41630000]      <1> 	cmp	al, [pfd] ; is same with previous drive # ?
  3724 00001D49 7423                <1> 	je	short gpndc	
  3725                              <1> 
  3726 00001D4B A2[41630000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3727                              <1> 
  3728 00001D50 53                  <1> 	push	ebx ; 08/02/2015
  3729                              <1> 	
  3730                              <1> 	;mov	bl, al 
  3731                              <1> 	; 11/12/2014
  3732                              <1> 	;mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3733                              <1> 	; 11/07/2022
  3734 00001D51 8A87[4C630000]      <1> 	mov	al, [edi+fd0_type]	; Drive type (0,1,2,3,4)	
  3735                              <1> 	; 18/12/2014
  3736 00001D57 20C0                <1> 	and	al, al
  3737 00001D59 7507                <1> 	jnz	short gpdtc
  3738 00001D5B BB[2B630000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3739 00001D60 EB05                <1>         jmp     short gpdpu
  3740                              <1> gpdtc:	
  3741 00001D62 E89DFBFFFF          <1> 	call	DR_TYPE_CHECK
  3742                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3743                              <1> gpdpu:
  3744 00001D67 891D[C8620000]      <1> 	mov	[DISK_POINTER], ebx
  3745 00001D6D 5B                  <1> 	pop	ebx
  3746                              <1> gpndc:
  3747                              <1> 	;mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3748                              <1> 	;mov	ah, [esi+ebx]		; GET THE WORD
  3749                              <1> 	; 11/07/2022
  3750 00001D6E 031D[C8620000]      <1> 	add	ebx, [DISK_POINTER]
  3751 00001D74 8A23                <1> 	mov	ah, [ebx] 
  3752 00001D76 5B                  <1> 	pop	ebx			; RESTORE EBX
  3753                              <1> 	;pop	esi ; 11/07/2022
  3754 00001D77 C3                  <1> 	retn
  3755                              <1> 
  3756                              <1> ;-------------------------------------------------------------------------------
  3757                              <1> ; MOTOR_ON
  3758                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3759                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3760                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3761                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3762                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3763                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3764                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3765                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3766                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3767                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3768                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3769                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3770                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3771                              <1> ;
  3772                              <1> ; ON ENTRY:	EDI = DRIVE #
  3773                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3774                              <1> ;-------------------------------------------------------------------------------
  3775                              <1> MOTOR_ON:
  3776                              <1> 	; 12/07/2022
  3777                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3778 00001D78 53                  <1> 	push	ebx			; SAVE REG.
  3779 00001D79 E820000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3780 00001D7E 721C                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3781                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3782                              <1> 	; 08/07/2022
  3783                              <1> 	;call	XLAT_NEW ; 12/07/2022	; TRANSLATE STATE TO PRESENT ARCH,
  3784                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3785                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3786                              <1> M_WAIT:
  3787                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3788 00001D80 B00A                <1> 	mov	al, 10 ; 08/07/2022
  3789 00001D82 E8B6FFFFFF          <1> 	call	GET_PARM
  3790                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3791 00001D87 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3792                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3793 00001D8A 7302                <1> 	jae	short J13
  3794 00001D8C B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3795                              <1> 
  3796                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3797                              <1> GP2:	
  3798                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3799                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3800 00001D8E B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3801 00001D93 E800F7FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3802                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3803 00001D98 FECC                <1> 	dec	ah
  3804 00001D9A 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3805                              <1> MOT_IS_ON:
  3806 00001D9C 5B                  <1> 	pop	ebx			; RESTORE REG.
  3807 00001D9D C3                  <1> 	retn
  3808                              <1> 
  3809                              <1> ;-------------------------------------------------------------------------------
  3810                              <1> ; TURN_ON
  3811                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3812                              <1> ;
  3813                              <1> ; ON ENTRY:	EDI = DRIVE #
  3814                              <1> ;
  3815                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3816                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3817                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3818                              <1> ;-------------------------------------------------------------------------------
  3819                              <1> TURN_ON:
  3820                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3821 00001D9E 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3822 00001DA0 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3823 00001DA2 C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3824 00001DA5 FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3825 00001DA6 C605[AB680000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3826 00001DAD A0[AA680000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3827 00001DB2 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3828 00001DB4 B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3829 00001DB6 D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3830                              <1> 
  3831                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3832                              <1> ;  BL = DRIVE SELECT DESIRED
  3833                              <1> ;  AH = MOTOR ON MASK DESIRED
  3834                              <1> 
  3835 00001DB8 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3836 00001DBA 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3837 00001DBC 8425[AA680000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3838 00001DC2 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3839                              <1> 
  3840                              <1> TURN_IT_ON:
  3841 00001DC4 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3842 00001DC6 8A3D[AA680000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3843 00001DCC 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3844 00001DCF 8025[AA680000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3845 00001DD6 0825[AA680000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3846 00001DDC A0[AA680000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3847 00001DE1 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3848 00001DE3 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3849 00001DE6 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3850 00001DE7 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3851 00001DE9 C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3852 00001DEC 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3853 00001DEE 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3854 00001DF2 EE                  <1> 	out	dx, al
  3855 00001DF3 38FB                <1> 	cmp	bl, bh			; NEW MOTOR TURNED ON ?
  3856                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3857 00001DF5 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3858 00001DF7 F8                  <1> 	clc				; RESET CARRY MEANING WAIT
  3859 00001DF8 C3                  <1> 	retn
  3860                              <1> 
  3861                              <1> NO_MOT_WAIT:
  3862 00001DF9 FB                  <1> 	sti
  3863                              <1> no_mot_w1: ; 27/02/2015
  3864 00001DFA F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3865                              <1> 	;sti				; INTERRUPTS BACK ON
  3866 00001DFB C3                  <1> 	retn
  3867                              <1> 
  3868                              <1> ;-------------------------------------------------------------------------------
  3869                              <1> ; HD_WAIT
  3870                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3871                              <1> ;
  3872                              <1> ; ON ENTRY:	DI = DRIVE #
  3873                              <1> ;
  3874                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  3875                              <1> ;-------------------------------------------------------------------------------
  3876                              <1> HD_WAIT:
  3877                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3878                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3879 00001DFC B009                <1> 	mov	al, 9	; 08/07/2022
  3880 00001DFE E83AFFFFFF          <1> 	CALL	GET_PARM
  3881 00001E03 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3882 00001E05 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3883 00001E07 F605[AA680000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3884                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3885                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3886                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3887 00001E0E 741D                <1> 	jz	short HW_DONE
  3888 00001E10 B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3889 00001E12 8A87[B7680000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3890 00001E18 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3891 00001E1A 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3892 00001E1C 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3893                              <1> ;GP3:
  3894 00001E1E B414                <1> 	mov	ah, HD320_SETTLE		; USE 320/360 HEAD SETTLE
  3895                              <1> ;	jmp	short DO_WAT
  3896                              <1> 
  3897                              <1> ;ISNT_WRITE:
  3898                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3899                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3900                              <1> 
  3901                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3902                              <1> DO_WAT:
  3903                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3904                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3905                              <1> J29:					; 	1 MILLISECOND LOOP
  3906                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3907                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3908                              <1> 	; 08/07/2022
  3909 00001E20 29C9                <1> 	sub	ecx, ecx
  3910 00001E22 B142                <1> 	mov	cl, 66
  3911 00001E24 E86FF6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3912                              <1> 	;dec	al			; DECREMENT THE COUNT
  3913 00001E29 FECC                <1> 	dec	ah
  3914 00001E2B 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3915                              <1> HW_DONE:
  3916 00001E2D C3                  <1> 	retn
  3917                              <1> 
  3918                              <1> ;-------------------------------------------------------------------------------
  3919                              <1> ; NEC_OUTPUT
  3920                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3921                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3922                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3923                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3924                              <1> ; 
  3925                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3926                              <1> ;
  3927                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3928                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3929                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3930                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3931                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3932                              <1> ;
  3933                              <1> ;		EAX, ECX, EDX DESTROYED
  3934                              <1> ;-------------------------------------------------------------------------------
  3935                              <1> 
  3936                              <1> ; 09/12/2014 [Erdogan Tan] 
  3937                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3938                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3939                              <1> ;	This read only register facilitates the transfer of data between
  3940                              <1> ;	the system microprocessor and the controller.
  3941                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3942                              <1> ;	  with the system micrprocessor.
  3943                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3944                              <1> ;	  the transfer is to the controller.
  3945                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3946                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3947                              <1> ; Bit 3 - Reserved.
  3948                              <1> ; Bit 2 - Reserved.
  3949                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3950                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3951                              <1> 
  3952                              <1> ; Data Register (3F5h)
  3953                              <1> ; This read/write register passes data, commands and parameters, and provides
  3954                              <1> ; diskette status information.
  3955                              <1>   		
  3956                              <1> NEC_OUTPUT:
  3957                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3958                              <1> 	;push	ebx			; SAVE REG.
  3959 00001E2E BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  3960                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  3961                              <1> 	; 16/12/2014
  3962                              <1> 	; waiting for (max.) 0.5 seconds
  3963                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  3964                              <1> 	;
  3965                              <1> 	; 17/12/2014
  3966                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  3967                              <1> 	;
  3968                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  3969                              <1> 	;		go on.
  3970                              <1> 	;INPUT:
  3971                              <1> 	;	AH=Mask for isolation bits.
  3972                              <1> 	;	AL=pattern to look for.
  3973                              <1> 	;	DX=Port to test for
  3974                              <1> 	;	ECX=Number of memory refresh periods to delay.
  3975                              <1> 	;	     (normally 30 microseconds per period.)
  3976                              <1> 	;
  3977                              <1> 	;WFP_SHORT:  
  3978                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  3979                              <1> 	;
  3980                              <1> 
  3981 00001E33 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  3982                              <1> ;
  3983                              <1> ;WFPS_OUTER_LP:
  3984                              <1> ;	;
  3985                              <1> ;WFPS_CHECK_PORT:
  3986                              <1> J23:
  3987 00001E38 EC                  <1> 	in	al, dx			; GET STATUS
  3988 00001E39 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  3989 00001E3B 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  3990 00001E3D 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  3991                              <1> WFPS_HI:
  3992 00001E3F E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  3993 00001E41 A810                <1> 	test	al, 010h		; transition on memory
  3994 00001E43 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  3995                              <1> WFPS_LO:
  3996 00001E45 E461                <1> 	in	al, PORT_B		; SYS1
  3997 00001E47 A810                <1> 	test	al, 010h
  3998 00001E49 74FA                <1> 	jz	short WFPS_LO
  3999                              <1> 	;loop	short WFPS_CHECK_PORT
  4000 00001E4B E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  4001                              <1> 
  4002                              <1> 	; fail
  4003                              <1> 
  4004                              <1> ;WFPS_TIMEOUT:
  4005                              <1> 
  4006                              <1> ;-----	FALL THRU TO ERROR RETURN
  4007                              <1> 
  4008 00001E4D 800D[AC680000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4009                              <1> 	;pop	ebx			; RESTORE REG.
  4010 00001E54 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4011 00001E55 F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  4012 00001E56 C3                  <1> 	retn
  4013                              <1> 
  4014                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4015                              <1> 
  4016                              <1> J27:	
  4017 00001E57 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  4018 00001E59 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  4019 00001E5A EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  4020                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4021                              <1> 	; 27/02/2015
  4022 00001E5B 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  4023                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4024 00001E5C 29C9                <1> 	sub	ecx, ecx
  4025 00001E5E B103                <1> 	mov	cl, 3 ; 24/12/2021
  4026 00001E60 E833F6FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  4027 00001E65 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  4028                              <1> 	;pop	ebx			; RESTORE REG
  4029 00001E66 C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  4030                              <1> 
  4031                              <1> ;-------------------------------------------------------------------------------
  4032                              <1> ; SEEK
  4033                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4034                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4035                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4036                              <1> ;
  4037                              <1> ; ON ENTRY:	EDI = DRIVE #
  4038                              <1> ;		CH = TRACK #
  4039                              <1> ;
  4040                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4041                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4042                              <1> ;-------------------------------------------------------------------------------
  4043                              <1> SEEK:
  4044                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4045 00001E67 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4046 00001E69 B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4047 00001E6B 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  4048 00001E6D D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  4049 00001E6F 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  4050 00001E71 8405[A9680000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4051 00001E77 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4052                              <1> 
  4053 00001E79 0805[A9680000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4054 00001E7F E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4055 00001E84 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  4056                              <1> 
  4057                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4058                              <1> 
  4059 00001E86 C605[AC680000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  4060 00001E8D E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4061 00001E92 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4062                              <1> 
  4063                              <1> AFT_RECAL:
  4064 00001E94 C687[B9680000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  4065 00001E9B 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  4066 00001E9D 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4067                              <1> 
  4068                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4069                              <1> 
  4070 00001E9F F687[B7680000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4071 00001EA6 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4072 00001EA8 D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  4073                              <1> 
  4074 00001EAA 3AAF[B9680000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  4075 00001EB0 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  4076                              <1> 
  4077 00001EB2 BA[E51E0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  4078 00001EB7 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4079 00001EB8 88AF[B9680000]      <1> 	mov	[DSK_TRK+edi], ch	; SAVE NEW CYLINDER AS PRESENT POSITION
  4080 00001EBE B40F                <1> 	mov	ah, 0Fh			; SEEK COMMAND TO NEC
  4081 00001EC0 E869FFFFFF          <1> 	call	NEC_OUTPUT
  4082 00001EC5 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4083 00001EC7 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  4084 00001EC9 E860FFFFFF          <1> 	call	NEC_OUTPUT
  4085 00001ECE 8AA7[B9680000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  4086 00001ED4 E855FFFFFF          <1> 	call	NEC_OUTPUT
  4087 00001ED9 E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4088                              <1> 
  4089                              <1> ;-----	WAIT FOR HEAD SETTLE
  4090                              <1> 
  4091                              <1> DO_WAIT:
  4092 00001EDE 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  4093 00001EDF E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4094 00001EE4 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  4095                              <1> RB:
  4096                              <1> NEC_ERR:
  4097                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4098                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4099 00001EE5 C3                  <1> 	retn				; RETURN TO CALLER
  4100                              <1> 
  4101                              <1> ;-------------------------------------------------------------------------------
  4102                              <1> ; RECAL
  4103                              <1> ;	RECALIBRATE DRIVE
  4104                              <1> ;
  4105                              <1> ; ON ENTRY:	EDI = DRIVE #
  4106                              <1> ;
  4107                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4108                              <1> ;-------------------------------------------------------------------------------
  4109                              <1> RECAL:
  4110                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4111                              <1> 	;push	cx
  4112                              <1> 	; 24/12/2021
  4113 00001EE6 51                  <1> 	push	ecx
  4114 00001EE7 B8[031F0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4115 00001EEC 50                  <1> 	push	eax
  4116 00001EED B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4117 00001EEF E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4118 00001EF4 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4119 00001EF6 88DC                <1> 	mov	ah, bl
  4120 00001EF8 E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4121 00001EFD E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4122 00001F02 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4123                              <1> RC_BACK:
  4124                              <1> 	;pop	cx
  4125                              <1> 	; 24/12/2021
  4126 00001F03 59                  <1> 	pop	ecx
  4127 00001F04 C3                  <1> 	RETn
  4128                              <1> 
  4129                              <1> ;-------------------------------------------------------------------------------
  4130                              <1> ; CHK_STAT_2
  4131                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4132                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4133                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4134                              <1> ;
  4135                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4136                              <1> ;-------------------------------------------------------------------------------
  4137                              <1> CHK_STAT_2:
  4138                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4139 00001F05 B8[2D1F0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4140 00001F0A 50                  <1> 	push	eax
  4141 00001F0B E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4142 00001F10 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4143 00001F12 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4144 00001F14 E815FFFFFF          <1> 	call	NEC_OUTPUT
  4145 00001F19 E849000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4146 00001F1E 720C                <1> 	jc	short J34
  4147 00001F20 A0[AD680000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4148 00001F25 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4149 00001F27 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4150 00001F29 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4151 00001F2B F8                  <1> 	clc				; GOOD RETURN
  4152                              <1> J34:
  4153 00001F2C 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4154                              <1> CS_BACK:
  4155 00001F2D C3                  <1> 	retn
  4156                              <1> J35:
  4157 00001F2E 800D[AC680000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4158 00001F35 F9                  <1> 	stc				; ERROR RETURN CODE
  4159 00001F36 EBF4                <1> 	jmp	short J34
  4160                              <1> 
  4161                              <1> ;-------------------------------------------------------------------------------
  4162                              <1> ; WAIT_INT
  4163                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4164                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4165                              <1> ;	IF THE DRIVE IS NOT READY.
  4166                              <1> ;
  4167                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4168                              <1> ;-------------------------------------------------------------------------------
  4169                              <1> 
  4170                              <1> ; 17/12/2014
  4171                              <1> ; 2.5 seconds waiting !
  4172                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4173                              <1> ; amount of time to wait for completion interrupt from NEC.
  4174                              <1> 
  4175                              <1> WAIT_INT:
  4176                              <1> 	; 12/07/2022
  4177                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4178 00001F38 FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4179                              <1> 	; 12/07/2022
  4180                              <1> 	;clc				; CLEAR TIMEOUT INDICATOR
  4181                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4182                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4183                              <1> 
  4184                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4185                              <1> 	;
  4186                              <1> 	;WAIT_FOR_MEM:	
  4187                              <1> 	;	Waits for a bit at a specified memory location pointed
  4188                              <1> 	;	to by ES:[DI] to become set.
  4189                              <1> 	;INPUT:
  4190                              <1> 	;	AH=Mask to test with.
  4191                              <1> 	;	ES:[DI] = memory location to watch.
  4192                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4193                              <1> 	;	     (normally 30 microseconds per period.)
  4194                              <1> 
  4195                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4196                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4197                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4198                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4199                              <1> 	; 27/02/2015
  4200 00001F39 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4201                              <1> WFMS_CHECK_MEM:
  4202 00001F3E F605[A9680000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4203 00001F45 7516                <1>         jnz     short J37
  4204                              <1> WFMS_HI:
  4205 00001F47 E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4206 00001F49 A810                <1> 	test	al, 010h		; transition on memory
  4207 00001F4B 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4208                              <1> WFMS_LO:
  4209 00001F4D E461                <1> 	in	al, PORT_B		; SYS1
  4210 00001F4F A810                <1> 	test	al, 010h
  4211 00001F51 74FA                <1> 	jz	short WFMS_LO
  4212 00001F53 E2E9                <1>         loop	WFMS_CHECK_MEM
  4213                              <1> ;WFMS_OUTER_LP:
  4214                              <1> ;;	or	bl, bl			; check outer counter
  4215                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4216                              <1> ;	dec	bl
  4217                              <1> ;	jz	short J36A	
  4218                              <1> ;	jmp	short WFMS_CHECK_MEM
  4219                              <1> 
  4220                              <1> 	;17/12/2014
  4221                              <1> 	;16/12/2014
  4222                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4223                              <1> ;J36:
  4224                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4225                              <1> ;	jnz	short J37
  4226                              <1> 	;16/12/2014
  4227                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4228                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4229                              <1> 	;jnz	short J36
  4230                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4231                              <1> ;	jb	short J36
  4232                              <1> 
  4233                              <1> ;WFMS_TIMEOUT:
  4234                              <1> ;J36A:
  4235 00001F55 800D[AC680000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4236 00001F5C F9                  <1> 	stc				; ERROR RETURN
  4237                              <1> J37:
  4238 00001F5D 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4239 00001F5E 8025[A9680000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4240 00001F65 9D                  <1> 	popf				; RECOVER CARRY
  4241 00001F66 C3                  <1> 	retn				; GOOD RETURN CODE
  4242                              <1> 
  4243                              <1> ;-------------------------------------------------------------------------------
  4244                              <1> ; RESULTS
  4245                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4246                              <1> ;	FOLLOWING AN INTERRUPT.
  4247                              <1> ;
  4248                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4249                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4250                              <1> ;-------------------------------------------------------------------------------
  4251                              <1> RESULTS:
  4252                              <1> 	; 12/07/2022
  4253                              <1> 	; 11/07/2022
  4254                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4255 00001F67 57                  <1> 	push	edi
  4256 00001F68 BF[AD680000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4257 00001F6D B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4258 00001F6F 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4259                              <1> 
  4260                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4261                              <1> 
  4262                              <1> _R10: 
  4263                              <1> 	; 16/12/2014
  4264                              <1> 	; wait for (max) 0.5 seconds
  4265                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4266                              <1> 	;xor	cx, cx			; COUNTER
  4267                              <1> 
  4268                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4269                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4270                              <1> 	; 27/02/2015
  4271                              <1> 
  4272 00001F73 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4273                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4274                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4275                              <1> 
  4276                              <1> WFPSR_OUTER_LP:
  4277                              <1> 	;
  4278                              <1> WFPSR_CHECK_PORT:
  4279                              <1> J39:					; WAIT FOR MASTER
  4280 00001F78 EC                  <1> 	in	al, dx			; GET STATUS
  4281 00001F79 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4282 00001F7B 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4283 00001F7D 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4284                              <1> WFPSR_HI:
  4285 00001F7F E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4286 00001F81 A810                <1> 	test	al, 010h		; transition on memory
  4287 00001F83 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4288                              <1> WFPSR_LO:
  4289 00001F85 E461                <1> 	in	al, PORT_B		; SYS1
  4290 00001F87 A810                <1> 	test	al, 010h
  4291 00001F89 74FA                <1> 	jz	short WFPSR_LO
  4292 00001F8B E2EB                <1>         loop	WFPSR_CHECK_PORT
  4293                              <1> 	
  4294                              <1> 	;; 27/02/2015
  4295                              <1> 	;;dec	bh
  4296                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4297                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4298                              <1> 
  4299                              <1> 	;;mov	byte [wait_count], 0
  4300                              <1> ;J39:					; WAIT FOR MASTER
  4301                              <1> ;	in	al, dx			; GET STATUS
  4302                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4303                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4304                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4305                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4306                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4307                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4308                              <1> 	;
  4309                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4310                              <1> 	;;jb	short J39	
  4311                              <1> 
  4312                              <1> ;WFPSR_TIMEOUT:
  4313 00001F8D 800D[AC680000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4314 00001F94 F9                  <1> 	stc				; SET ERROR RETURN
  4315 00001F95 EB26                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4316                              <1> 
  4317                              <1> ;-----	READ IN THE STATUS
  4318                              <1> 
  4319                              <1> J42:
  4320 00001F97 EB00                <1> 	JMP	$+2			; I/O DELAY
  4321                              <1> 	;inc	dx			; POINT AT DATA PORT
  4322 00001F99 FEC2                <1> 	inc	dl
  4323 00001F9B EC                  <1> 	in	al, dx			; GET THE DATA
  4324                              <1> 	; 16/12/2014
  4325                              <1> 	NEWIODELAY
  2175 00001F9C E6EB                <2>  out 0EBh,al
  4326                              <1> 	
  4327                              <1> 	;mov	[edi], al		; STORE THE BYTE
  4328                              <1> 	;inc	edi			; INCREMENT THE POINTER
  4329                              <1> 	; 11/07/2022
  4330 00001F9E AA                  <1> 	stosb
  4331                              <1> 
  4332                              <1> 	; 16/12/2014
  4333                              <1> ;	push	cx
  4334                              <1> ;	mov	cx, 30
  4335                              <1> ;wdw2:
  4336                              <1> ;	NEWIODELAY
  4337                              <1> ;	loop	wdw2
  4338                              <1> ;	pop	cx
  4339                              <1> 
  4340                              <1> 	;mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4341                              <1> 	; 12/07/2022
  4342 00001F9F 29C9                <1> 	sub	ecx, ecx
  4343 00001FA1 B103                <1> 	mov	cl, 3
  4344 00001FA3 E8F0F4FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4345                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4346 00001FA8 FECA                <1> 	dec	dl
  4347 00001FAA EC                  <1> 	in	al, dx			; GET STATUS
  4348                              <1> 	; 16/12/2014
  4349                              <1> 	NEWIODELAY
  2175 00001FAB E6EB                <2>  out 0EBh,al
  4350                              <1> 	;
  4351 00001FAD A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4352 00001FAF 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4353                              <1> 
  4354 00001FB1 FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4355 00001FB3 75BE                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4356 00001FB5 800D[AC680000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4357 00001FBC F9                  <1> 	stc				; SET ERROR FLAG
  4358                              <1> 
  4359                              <1> ;-----	RESULT OPERATION IS DONE
  4360                              <1> POPRES:
  4361 00001FBD 5F                  <1> 	pop	edi
  4362 00001FBE C3                  <1> 	retn				; RETURN WITH CARRY SET
  4363                              <1> 
  4364                              <1> ;-------------------------------------------------------------------------------
  4365                              <1> ; READ_DSKCHNG
  4366                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4367                              <1> ;
  4368                              <1> ; ON ENTRY:	EDI = DRIVE #
  4369                              <1> ;
  4370                              <1> ; ON EXIT:	EDI = DRIVE #
  4371                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4372                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4373                              <1> ;		EAX, ECX, EDX DESTROYED
  4374                              <1> ;-------------------------------------------------------------------------------
  4375                              <1> READ_DSKCHNG:
  4376                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4377 00001FBF E8B4FDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4378 00001FC4 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4379 00001FC8 EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4380 00001FC9 A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4381 00001FCB C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4382                              <1> 
  4383                              <1> fdc_int:  
  4384                              <1> 	  ; 30/07/2015	
  4385                              <1> 	  ; 16/02/2015
  4386                              <1> ;int_0Eh: ; 11/12/2014
  4387                              <1> 
  4388                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL 6 ) ---------------------------------------
  4389                              <1> ; DISK_INT
  4390                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4391                              <1> ;
  4392                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4393                              <1> ;-------------------------------------------------------------------------------
  4394                              <1> DISK_INT_1:
  4395                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4396                              <1> 	;push	eax			; SAVE WORK REGISTER
  4397                              <1> 	; 24/12/2021
  4398 00001FCC 50                  <1> 	push	eax
  4399 00001FCD 1E                  <1> 	push	ds
  4400 00001FCE 66B81000            <1> 	mov	ax, KDATA
  4401 00001FD2 8ED8                <1> 	mov 	ds, ax
  4402 00001FD4 800D[A9680000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4403 00001FDB B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4404 00001FDD E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4405 00001FDF 1F                  <1> 	pop	ds
  4406                              <1> 	;pop	ax			; RECOVER REGISTER
  4407                              <1> 	; 24/12/2021
  4408 00001FE0 58                  <1> 	pop	eax
  4409 00001FE1 CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4410                              <1> 
  4411                              <1> ;-------------------------------------------------------------------------------
  4412                              <1> ; DSKETTE_SETUP
  4413                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4414                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4415                              <1> ;-------------------------------------------------------------------------------
  4416                              <1> DSKETTE_SETUP:
  4417                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4418                              <1> 	;push	eax			; SAVE REGISTERS
  4419                              <1> 	;push	ebx
  4420                              <1> 	;push	ecx
  4421 00001FE2 52                  <1> 	push	edx
  4422                              <1> 	;push	edi
  4423                              <1> 	; 14/12/2014
  4424                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4425                              <1> 	;
  4426                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4427                              <1> 
  4428 00001FE3 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4429 00001FE5 29C9                <1> 	sub	ecx, ecx
  4430 00001FE7 66890D[B7680000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4431                              <1> 	; 08/07/2022
  4432                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4433 00001FEE 800D[B4680000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4434 00001FF5 880D[A9680000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4435 00001FFB 880D[AB680000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4436 00002001 880D[AA680000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4437 00002007 880D[AC680000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4438                              <1> 	;
  4439                              <1> 	; 28/02/2015
  4440                              <1> 	;mov	word [cfd], 100h 
  4441 0000200D E87FF8FFFF          <1> 	call	DSK_RESET
  4442 00002012 5A                  <1> 	pop	edx
  4443 00002013 C3                  <1> 	retn
  4444                              <1> 
  4445                              <1> ;//////////////////////////////////////////////////////
  4446                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4447                              <1> ;
  4448                              <1> 
  4449                              <1> ; 12/07/2022
  4450                              <1> ;int13h: ; 21/02/2015
  4451                              <1> ;	pushfd
  4452                              <1> ;	push 	cs
  4453                              <1> ;	call 	DISK_IO
  4454                              <1> ;	retn
  4455                              <1> 
  4456                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4457                              <1> ;/////////////////////////////////////////////////////////////////////
  4458                              <1> 
  4459                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4460                              <1> ; ((Direct call instead of int 13h simulation))
  4461                              <1> ;
  4462                              <1> ;		Function in AL
  4463                              <1> ;			0 = reset
  4464                              <1> ;			1 = read
  4465                              <1> ;			2 = write
  4466                              <1> ;		Disk drive number in DL
  4467                              <1> ;			0 & 1 = floppy disks	
  4468                              <1> ;			80h .. 83h = hard disks
  4469                              <1> ;		Sector address (LBA) in ECX
  4470                              <1> ;		Buffer address in EBX
  4471                              <1> ;		R/W sector count is (always) 1
  4472                              <1> ;
  4473                              <1> ;		Return:
  4474                              <1> ;			Status in AH (>0 = error code)
  4475                              <1> ;			if CF = 1 -> error code in AH
  4476                              <1> ;			if CF = 0 -> successful
  4477                              <1> ;			AL = undefined
  4478                              <1> ;
  4479                              <1> ;		Modified registers: (only) EAX
  4480                              <1> 
  4481                              <1> ; 10/07/2022
  4482                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4483                              <1> 
  4484                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4485                              <1> ; 23/02/2015
  4486                              <1> ; 21/02/2015 (unix386.s)
  4487                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4488                              <1> ;
  4489                              <1> ; Original Source Code:
  4490                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4491                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4492                              <1> ;
  4493                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4494                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4495                              <1> ;
  4496                              <1> 
  4497                              <1> ;The wait for controller to be not busy is 10 seconds.
  4498                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4499                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4500                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4501                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4502                              <1> 
  4503                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4504                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4505                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4506                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4507                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4508                              <1> 
  4509                              <1> ;The wait for Data request on read and write longs is
  4510                              <1> ;2000 us. (?)
  4511                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4512                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4513                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4514                              <1> 
  4515                              <1> ; Port 61h (PORT_B)
  4516                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4517                              <1> 
  4518                              <1> ; 23/12/2014
  4519                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4520                              <1> 
  4521                              <1> 	; 11/07/2022
  4522                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4523                              <1> 
  4524                              <1> ;--- INT 13H -------------------------------------------------------------------
  4525                              <1> ;									       :
  4526                              <1> ; FIXED DISK I/O INTERFACE						       :
  4527                              <1> ;									       :
  4528                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4529                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4530                              <1> ;									       :
  4531                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4532                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4533                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4534                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4535                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4536                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4537                              <1> ;									       :
  4538                              <1> ;------------------------------------------------------------------------------:
  4539                              <1> ;									       :
  4540                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4541                              <1> ;									       :
  4542                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4543                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY                        :
  4544                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY                       :
  4545                              <1> ;									       :
  4546                              <1> ;------------------------------------------------------------------------------:
  4547                              <1> ;									       :
  4548                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4549                              <1> ;									       :
  4550                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4551                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4552                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4553                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4554                              <1> ;									       :
  4555                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4556                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4557                              <1> ;				 (10 BITS TOTAL)			       :
  4558                              <1> ;									       :
  4559                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4560                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4561                              <1> ;									       :
  4562                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4563                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4564                              <1> ;									       :
  4565                              <1> ;------------------------------------------------------------------------------:
  4566                              <1> ; OUTPUT								       :
  4567                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4568                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4569                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4570                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4571                              <1> ;									       :
  4572                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4573                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4574                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4575                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4576                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4577                              <1> ;		REWRITTEN.						       :
  4578                              <1> ;									       :
  4579                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4580                              <1> ;	   INPUT:							       :
  4581                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4582                              <1> ;	   OUTPUT:							       :
  4583                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4584                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4585                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4586                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4587                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4588                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4589                              <1> ;									       :
  4590                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4591                              <1> ;	INFORMATION.							       :
  4592                              <1> ;									       :
  4593                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4594                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4595                              <1> ;									       :
  4596                              <1> ;-------------------------------------------------------------------------------
  4597                              <1> 
  4598                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4599                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4600                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4601                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4602                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4603                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4604                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4605                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4606                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4607                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4608                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4609                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4610                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4611                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4612                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4613                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4614                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4615                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4616                              <1> 
  4617                              <1> ;--------------------------------------------------------
  4618                              <1> ;							:
  4619                              <1> ; FIXED DISK PARAMETER TABLE				:
  4620                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4621                              <1> ;							:
  4622                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4623                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4624                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4625                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4626                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4627                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4628                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4629                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4630                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4631                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4632                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4633                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4634                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4635                              <1> ;							:
  4636                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4637                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4638                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4639                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4640                              <1> ;							:
  4641                              <1> ;--------------------------------------------------------
  4642                              <1> 
  4643                              <1> ;--------------------------------------------------------
  4644                              <1> ;							:
  4645                              <1> ; HARDWARE SPECIFIC VALUES				:
  4646                              <1> ;							:
  4647                              <1> ;  -  CONTROLLER I/O PORT				:
  4648                              <1> ;							:
  4649                              <1> ;     > WHEN READ FROM: 				:
  4650                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4651                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4652                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4653                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4654                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4655                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4656                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4657                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4658                              <1> ;							:
  4659                              <1> ;     > WHEN WRITTEN TO:				:
  4660                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4661                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4662                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4663                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4664                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4665                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4666                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4667                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4668                              <1> ;							:
  4669                              <1> ;--------------------------------------------------------
  4670                              <1> 
  4671                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4672                              <1> ;HF1_PORT	equ	0170h	
  4673                              <1> ;HF_REG_PORT	EQU	03F6H
  4674                              <1> ;HF1_REG_PORT	equ	0376h
  4675                              <1> 
  4676                              <1> HDC1_BASEPORT	equ	1F0h
  4677                              <1> HDC2_BASEPORT	equ	170h		
  4678                              <1> 
  4679                              <1> align 2
  4680                              <1> 
  4681                              <1> ;-----		STATUS REGISTER
  4682                              <1> 
  4683                              <1> ST_ERROR	EQU	00000001B	;
  4684                              <1> ST_INDEX	EQU	00000010B	;
  4685                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4686                              <1> ST_DRQ		EQU	00001000B	;
  4687                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4688                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4689                              <1> ST_READY	EQU	01000000B	;
  4690                              <1> ST_BUSY 	EQU	10000000B	;
  4691                              <1> 
  4692                              <1> ;-----		ERROR REGISTER
  4693                              <1> 
  4694                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4695                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4696                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4697                              <1> ;		EQU	00001000B	; NOT USED
  4698                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4699                              <1> ;		EQU	00100000B	; NOT USED
  4700                              <1> ERR_DATA_ECC	EQU	01000000B
  4701                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4702                              <1> 
  4703                              <1> 
  4704                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4705                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4706                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4707                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4708                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4709                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4710                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4711                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4712                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4713                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4714                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4715                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4716                              <1> 
  4717                              <1> ;MAX_FILE	EQU	2
  4718                              <1> ;S_MAX_FILE	EQU	2
  4719                              <1> MAX_FILE	equ	4		; 22/12/2014
  4720                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4721                              <1> 
  4722                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4723                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4724                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4725                              <1> 
  4726                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4727                              <1> 
  4728                              <1> ;-----		COMMAND BLOCK REFERENCE
  4729                              <1> 
  4730                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4731                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4732                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4733                              <1> ; 19/12/2014
  4734                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4735                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4736                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4737                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4738                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4739                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4740                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4741                              <1> 
  4742                              <1> align 2
  4743                              <1> 
  4744                              <1> ;----------------------------------------------------------------
  4745                              <1> ; FIXED DISK I/O SETUP						:
  4746                              <1> ;								:
  4747                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4748                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4749                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4750                              <1> ;								:
  4751                              <1> ;----------------------------------------------------------------
  4752                              <1> 
  4753                              <1> 	; 12/07/2022
  4754                              <1> 	; 11/07/2022
  4755                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4756                              <1> 
  4757                              <1> DISK_SETUP:
  4758                              <1> 	;cli
  4759                              <1> 	;;mov	ax, ABS0 			; GET ABSOLUTE SEGMENT
  4760                              <1> 	;xor	ax, ax
  4761                              <1> 	;mov	ds, ax				; SET SEGMENT REGISTER
  4762                              <1> 	;mov	ax, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4763                              <1> 	;mov	[DISK_VECTOR], ax		; INTO INT 40H
  4764                              <1> 	;mov	ax, [ORG_VECTOR+2]
  4765                              <1> 	;mov	[DISK_VECTOR+2], ax
  4766                              <1> 	;mov	word [ORG_VECTOR], DISK_IO	; FIXED DISK HANDLER
  4767                              <1> 	;mov	[ORG_VECTOR+2], cs
  4768                              <1> 	; 1st controller (primary master, slave) - IRQ 14
  4769                              <1> 	;;mov	word [HDISK_INT], HD_INT	; FIXED DISK INTERRUPT
  4770                              <1> 	;mov	word [HDISK_INT1], HD_INT	;
  4771                              <1> 	;;mov	[HDISK_INT+2], cs
  4772                              <1> 	;mov	[HDISK_INT1+2], cs
  4773                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4774                              <1> 	;mov	word [HDISK_INT2], HD1_INT	;
  4775                              <1> 	;mov	[HDISK_INT2+2], cs
  4776                              <1> 	;
  4777                              <1> 	;;mov	word [HF_TBL_VEC], HD0_DPT	; PARM TABLE DRIVE 80
  4778                              <1> 	;;mov	word [HF_TBL_VEC+2], DPT_SEGM
  4779                              <1> 	;;mov	word [HF1_TBL_VEC], HD1_DPT	; PARM TABLE DRIVE 81
  4780                              <1> 	;;mov	word [HF1_TBL_VEC+2], DPT_SEGM
  4781                              <1> 	;push	cs
  4782                              <1> 	;pop	ds
  4783                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4784                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4785 00002014 C705[C0680000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4785 0000201C 0900                <1>
  4786                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4787                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4788 0000201E C705[C4680000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4788 00002026 0900                <1>
  4789                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4790                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4791 00002028 C705[C8680000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4791 00002030 0900                <1>
  4792                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4793                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4794 00002032 C705[CC680000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4794 0000203A 0900                <1>
  4795                              <1> 	;
  4796                              <1> 	;;in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  4797                              <1> 	;;;and	al, 0BFh
  4798                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4799                              <1> 	;;;JMP	$+2
  4800                              <1> 	;;IODELAY
  4801                              <1> 	;;out	INTB01, al
  4802                              <1> 	;;IODELAY
  4803                              <1> 	;;in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  4804                              <1> 	;;and	al, 0FBh 		; SECOND CHIP
  4805                              <1> 	;;;JMP	$+2
  4806                              <1> 	;;IODELAY
  4807                              <1> 	;;out	INTA01, al
  4808                              <1> 	;
  4809                              <1> 	;sti
  4810                              <1> 	;;push	ds			; MOVE ABS0 POINTER TO
  4811                              <1> 	;;pop	es			; EXTRA SEGMENT POINTER
  4812                              <1> 	;;;call	DDS			; ESTABLISH DATA SEGMENT
  4813                              <1> 	;;mov	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4814                              <1> 	;;mov	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4815                              <1> 	;;mov	byte [CONTROL_BYTE],0
  4816                              <1> 	;;mov	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4817                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4818                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4819                              <1> 	;mov	si, hd0_type
  4820 0000203C BE[4E630000]        <1> 	mov	esi, hd0_type
  4821                              <1> 	;;mov	cx, 4
  4822                              <1> 	;mov	ecx, 4
  4823                              <1> 	; 11/07/2022
  4824 00002041 29C9                <1> 	sub	ecx, ecx
  4825 00002043 B104                <1> 	mov	cl, 4
  4826                              <1> hde_l:
  4827 00002045 AC                  <1> 	lodsb
  4828 00002046 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4829 00002048 7206                <1> 	jb	short _L4
  4830 0000204A FE05[BC680000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4831                              <1> _L4: ; 26/02/2015
  4832 00002050 E2F3                <1> 	loop	hde_l	
  4833                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4834                              <1> ;L4:
  4835                              <1> 	; 
  4836                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4837                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4838                              <1> 	;;mov 	cl, 3
  4839                              <1> 	;;
  4840                              <1> 	;;mov	dl, 80h			; CHECK THE CONTROLLER
  4841                              <1> ;;hdc_dl:
  4842                              <1> 	;;mov	ah, 14h			; USE CONTROLLER DIAGNOSTIC COMMAND
  4843                              <1> 	;;int	13h			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4844                              <1> 	;;;jc	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4845                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4846                              <1> 	;;jnc	short hdc_reset0
  4847                              <1> 	;;loop	hdc_dl
  4848                              <1> 	;;; 27/12/2014
  4849                              <1> 	;;stc
  4850                              <1> 	;;retn
  4851                              <1> 	;
  4852                              <1> ;;hdc_reset0:
  4853                              <1> 	; 18/01/2015
  4854 00002052 8A0D[BC680000]      <1> 	mov	cl, [HF_NUM]
  4855 00002058 20C9                <1> 	and	cl, cl
  4856 0000205A 740D                <1> 	jz	short POD_DONE
  4857                              <1> 	;
  4858 0000205C B27F                <1> 	mov	dl, 7Fh
  4859                              <1> hdc_reset1:
  4860 0000205E FEC2                <1> 	inc	dl
  4861                              <1> 	;; 31/12/2015
  4862                              <1> 	;;push	dx
  4863                              <1> 	;;push	cx
  4864                              <1> 	;;push	ds
  4865                              <1> 	;;sub	ax, ax
  4866                              <1> 	;;mov	ds, ax
  4867                              <1> 	;;mov	ax, [TIMER_LOW]		; GET START TIMER COUNTS
  4868                              <1> 	;;pop	ds
  4869                              <1> 	;;mov	bx, ax
  4870                              <1> 	;;add	ax, 6*182		; 60 SECONDS* 18.2
  4871                              <1> 	;;mov	cx, ax
  4872                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4873                              <1> 	;;
  4874                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4875                              <1> 	;;call	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4876                              <1> 	;;pop	cx
  4877                              <1> 	;;pop	dx
  4878                              <1> 	;;
  4879                              <1> 	; 18/01/2015
  4880                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4881                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4882                              <1> 	;mov	ah, 5 ; ALTERNATE RESET
  4883                              <1> 	;;int	13h
  4884                              <1> 	;call	int13h
  4885                              <1> 	; 12/07/2022
  4886 00002060 30C0                <1> 	xor	al, al  ; reset
  4887 00002062 E803000000          <1> 	call	DISK_IO	
  4888                              <1> 	;
  4889 00002067 E2F5                <1> 	loop	hdc_reset1
  4890                              <1> POD_DONE:
  4891 00002069 C3                  <1> 	RETn
  4892                              <1> 
  4893                              <1> ;----------------------------------------
  4894                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4895                              <1> ;----------------------------------------
  4896                              <1> 
  4897                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4898                              <1> ; ((Direct call instead of int 13h simulation))
  4899                              <1> ;
  4900                              <1> ;		Function in AL
  4901                              <1> ;			0 = reset
  4902                              <1> ;			1 = read
  4903                              <1> ;			2 = write
  4904                              <1> ;		Disk drive number in DL
  4905                              <1> ;			0 & 1 = floppy disks	
  4906                              <1> ;			80h .. 83h = hard disks
  4907                              <1> ;		Sector address (LBA) in ECX
  4908                              <1> ;		Buffer address in EBX
  4909                              <1> ;		R/W sector count is (always) 1
  4910                              <1> ;
  4911                              <1> ;		Return:
  4912                              <1> ;			Status in AH (>0 = error code)
  4913                              <1> ;			if CF = 1 -> error code in AH
  4914                              <1> ;			if CF = 0 -> successful
  4915                              <1> ;			AL = undefined
  4916                              <1> ;
  4917                              <1> ;		Modified registers: (only) EAX
  4918                              <1> 	
  4919                              <1> 
  4920                              <1> ; 11/07/2022
  4921                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4922                              <1> 
  4923                              <1> DISK_IO:
  4924                              <1> 	; 11/07/2022
  4925                              <1> 	; save registers
  4926 0000206A 57                  <1> 	push	edi			; ANY
  4927 0000206B 56                  <1> 	push	esi			; ANY
  4928 0000206C 53                  <1> 	push	ebx			; BUFFER ADDRESS
  4929 0000206D 51                  <1> 	push	ecx			; SECTOR ADDRESS (LBA)
  4930 0000206E 52                  <1> 	push	edx			; DRIVE NUMBER (DL)
  4931                              <1> 
  4932                              <1> 	;cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4933                              <1> 	;;jae	short A1		; YES, HANDLE HERE
  4934                              <1> 	;;;;int	40H			; DISKETTE HANDLER
  4935                              <1> 	;;;call	int40h
  4936                              <1> 	;;jb	DISKETTE_IO_1
  4937                              <1> 	;; 24/12/2021
  4938                              <1> 	;jnb	short A1
  4939                              <1> 	;jmp	DISKETTE_IO_1
  4940                              <1> 
  4941                              <1> 	; 11/07/2022
  4942 0000206F 80FA80              <1> 	cmp	dl, 80h
  4943 00002072 730B                <1> 	jae	short A1
  4944                              <1> 
  4945 00002074 E8B3F6FFFF          <1> 	call	DISKETTE_IO_1
  4946                              <1> 
  4947                              <1> DISK_IO_RTN:
  4948                              <1> 	; restore registers
  4949 00002079 5A                  <1> 	pop	edx
  4950 0000207A 59                  <1> 	pop	ecx
  4951 0000207B 5B                  <1> 	pop	ebx
  4952 0000207C 5E                  <1> 	pop	esi
  4953 0000207D 5F                  <1> 	pop	edi
  4954 0000207E C3                  <1> 	retn	
  4955                              <1> 
  4956                              <1> ;RET_2:
  4957                              <1> ;	retf	4			; BACK TO CALLER
  4958                              <1> 
  4959                              <1> A1:
  4960                              <1> 	; 11/07/2022
  4961                              <1> 	;sti				; ENABLE INTERRUPTS
  4962                              <1> 	;cmp	dl, (80h + S_MAX_FILE - 1)
  4963                              <1> 	;ja	short RET_2
  4964                              <1> 	
  4965                              <1> 	; 18/01/2015
  4966                              <1> 	;;or	ah, ah
  4967                              <1> 	;or	al, al ; 11/07/2022 (reset function)
  4968                              <1> 	;jz	short A3 ; 08/07/2022
  4969                              <1> 	
  4970                              <1> 	;;cmp	ah, 5  ; Alternate reset
  4971                              <1> 	;cmp	al, 5  ; 11/07/2022
  4972                              <1> 	;je	short A2
  4973                              <1> 	
  4974                              <1> 	; 11/07/2022 - no need to check
  4975                              <1> 	;		 (only kernel calls diskio functions)
  4976                              <1> 	;;cmp	ah, M1L/4 ; cmp ah, 6
  4977                              <1> 	;jb	short A3
  4978                              <1> 	;; BAD COMMAND
  4979                              <1>         ;mov     byte [DISK_STATUS1], BAD_CMD
  4980                              <1> ;RET_2:
  4981                              <1> 	;retf	4
  4982                              <1> 
  4983                              <1> 	; 11/07/2022
  4984                              <1> 	;stc
  4985                              <1> 	;retn
  4986                              <1> A2:
  4987                              <1> 	;sub	ah, ah	; Reset
  4988                              <1> 	; 11/07/2022
  4989                              <1> 	;sub	al, al
  4990                              <1> A3:
  4991                              <1> 					; SAVE REGISTERS DURING OPERATION
  4992 0000207F C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  4993                              <1> 	
  4994                              <1> 	; 11/07/2022
  4995                              <1> 	; 08/07/2022
  4996                              <1> 	;push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  4997                              <1> 	;push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  4998                              <1> 	;push	edx
  4999                              <1> 	;push	esi
  5000                              <1> 	;push	edi
  5001                              <1> 	
  5002 00002083 E80D000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  5003                              <1> 
  5004 00002088 C9                  <1> 	leave	; 11/07/2022
  5005                              <1> 	
  5006 00002089 8A25[BB680000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  5007 0000208F 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  5008 00002092 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  5009                              <1> 	
  5010                              <1> 	;pop	edi			; RESTORE REGISTERS
  5011                              <1> 	;pop	esi
  5012                              <1>       	;pop	edx
  5013                              <1> 	;pop	ecx
  5014                              <1> 	;pop	ebx
  5015                              <1> 	
  5016                              <1> 	;leave				; ADJUST (ESP) AND RESTORE (EBP)
  5017                              <1> 	
  5018                              <1> 	; 11/07/2022
  5019                              <1> 	;retf	4			; THROW AWAY SAVED FLAGS
  5020                              <1> 
  5021 00002093 EBE4                <1> 	jmp	short DISK_IO_RTN
  5022                              <1> 
  5023                              <1> DISK_IO_CONT:
  5024                              <1> 	; 11/07/2022
  5025                              <1> 	;	INPUT:
  5026                              <1> 	;	    AL = 0 : reset
  5027                              <1> 	;	    AL = 1 : read
  5028                              <1> 	;	    Al = 2 : write
  5029                              <1> 	; 	
  5030                              <1> 	; 10/07/2022
  5031                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5032                              <1> SU0:
  5033 00002095 C605[BB680000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  5034                              <1> 	; 10/07/2022
  5035 0000209C 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  5036                              <1> 
  5037 0000209E 8A1D[BC680000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  5038 000020A4 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  5039                              <1> 					; (get drive number as 0 to 3)
  5040 000020A7 38D3                <1> 	cmp	bl, dl
  5041                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  5042                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5043                              <1> 	; 24/12/2021
  5044 000020A9 7705                <1> 	ja	short su0_su1
  5045 000020AB E98D000000          <1> 	jmp	BAD_COMMAND
  5046                              <1> su0_su1:
  5047                              <1>         ;;03/01/2015
  5048 000020B0 29DB                <1> 	sub	ebx, ebx
  5049 000020B2 88D3                <1> 	mov	bl, dl
  5050 000020B4 883D[D0680000]      <1> 	mov	[LBAMode], bh  ; 0
  5051                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  5052                              <1> 	;jz	short su1		; no
  5053                              <1> 	;inc	byte [LBAMode]
  5054                              <1> ;su1:
  5055                              <1> 	; 21/02/2015 (32 bit modification)
  5056                              <1> 	; 04/01/2015
  5057                              <1> 	;push	ax ; ***
  5058                              <1> 	; 24/12/2021
  5059 000020BA 50                  <1> 	push	eax ; *** ; function (in AL) ; 11/07/2022
  5060                              <1> 	; 24/12/2021
  5061 000020BB 52                  <1> 	push	edx ; *
  5062 000020BC 50                  <1> 	push	eax ; function (in AL)	; 11/07/2022
  5063 000020BD E8CB030000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5064                              <1> 	; 02/02/2015
  5065 000020C2 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  5066 000020C6 66A3[42630000]      <1> 	mov	[HF_PORT], ax
  5067 000020CC 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  5068 000020D0 668915[44630000]    <1> 	mov	[HF_REG_PORT], dx
  5069 000020D7 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  5070                              <1> 	; 23/02/2015
  5071 000020DA A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5072 000020DC 7406                <1> 	jz 	short su1
  5073 000020DE FE05[D0680000]      <1> 	inc	byte [LBAMode] ; 1 
  5074                              <1> su1: 	 
  5075 000020E4 C0E804              <1> 	shr 	al, 4
  5076 000020E7 2401                <1> 	and	al, 1			
  5077 000020E9 A2[46630000]        <1> 	mov	[hf_m_s], al 
  5078                              <1> 	;
  5079                              <1> 	; 03/01/2015
  5080 000020EE 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5081                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  5082 000020F1 EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  5083                              <1> 					; Control Byte: (= 08h, here)
  5084                              <1> 					; bit 0 - 0
  5085                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5086                              <1> 					; bit 2 - SRST (software RESET)
  5087                              <1> 					; bit 3 - use extra heads (8 to 15)
  5088                              <1> 					;         -always set to 1-	
  5089                              <1> 					; (bits 3 to 7 are reserved
  5090                              <1> 					;          for ATA devices)
  5091 000020F2 8A25[BD680000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5092 000020F8 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  5093 000020FB 08C4                <1> 	or	ah, al
  5094 000020FD 8825[BD680000]      <1> 	mov	[CONTROL_BYTE], ah	
  5095                              <1> 	; 04/01/2015
  5096                              <1> 	;pop	ax
  5097                              <1> 	; 24/12/2021
  5098 00002103 58                  <1> 	pop	eax ; function (in AL) ; 11/07/2022
  5099                              <1> 	;pop	dx ; * ;; 14/02/2015
  5100                              <1> 	; 24/12/2021
  5101 00002104 5A                  <1> 	pop	edx ; *
  5102                              <1> 	;and	ah, ah	; Reset function ?
  5103 00002105 20C0                <1> 	and	al, al	; 11/07/2022
  5104 00002107 7506                <1> 	jnz	short su2
  5105                              <1> 	;pop	ax ; ***
  5106                              <1> 	; 24/12/2021
  5107 00002109 58                  <1> 	pop	eax ; *** 	
  5108                              <1> 	;;pop	bx
  5109 0000210A E9EB000000          <1>         jmp     DISK_RESET
  5110                              <1> su2:
  5111                              <1> 	; 11/07/2022
  5112                              <1> 	; ecx = sector address (lba)
  5113                              <1> 	;  dl = hard disk drive number (80h, 81h .. 83h)	 
  5114                              <1> 	;  al = function (0 = read, 1 = write)	
  5115                              <1> 
  5116 0000210F 803D[D0680000]00    <1> 	cmp	byte [LBAMode], 0
  5117 00002116 7620                <1> 	jna	short su3 ; convert LBA address to CHS parameters
  5118                              <1> 	
  5119                              <1> ;	; 02/02/2015 (LBA read/write function calls)
  5120                              <1> ;	;cmp	ah, 1Bh
  5121                              <1> ;	cmp	ah, 3 ; 08/07/2022
  5122                              <1> ;	jb	short lbarw1
  5123                              <1> ;	;;cmp	ah, 1Ch
  5124                              <1> ;	;cmp	ah, 4 ; 08/07/2022 
  5125                              <1> ;	;ja 	short invldfnc
  5126                              <1> ;	;;pop	dx ; * ; 14/02/2015
  5127                              <1> ;	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5128                              <1> 
  5129 00002118 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5130                              <1> 
  5131                              <1> 	; 11/07/2022
  5132                              <1> 	;; 14/02/2015
  5133                              <1> 	;mov	cl, dl ; 14/02/2015
  5134                              <1> 
  5135                              <1> 	;;mov	dx, bx
  5136                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5137                              <1> 	;;mov	bx, di
  5138                              <1> 	;mov	si, di ; Buffer offset
  5139                              <1> 
  5140                              <1> 	; 11/07/2022
  5141                              <1> 	;jmp	short lbarw2
  5142                              <1> 
  5143                              <1> ;lbarw1:
  5144                              <1> ;	; convert CHS to LBA
  5145                              <1> ;	;
  5146                              <1> ;	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5147                              <1> ;	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5148                              <1> ;	;	+ Sector - 1
  5149                              <1> ;	;push	dx ; * ;; 14/02/2015
  5150                              <1> ;	; 24/12/2021
  5151                              <1> ;	push	edx ; *
  5152                              <1> ;	;xor	dh, dh
  5153                              <1> ;	xor	edx, edx
  5154                              <1> ;	mov	dl, [ebx+14]	; sectors per track (logical)
  5155                              <1> ;	;xor	ah, ah
  5156                              <1> ;	xor	eax, eax
  5157                              <1> ;	mov	al, [ebx+2]	; heads (logical) 
  5158                              <1> ;	dec	al
  5159                              <1> ;	;inc	ax		; 0 =  256
  5160                              <1> ;	inc	eax ; 24/12/2021
  5161                              <1> ;	mul 	dx
  5162                              <1> ;		; AX = # of Heads * Sectors/Track
  5163                              <1> ;	mov	dx, cx
  5164                              <1> ;	;and	cx, 3Fh	 ; sector (1 to 63)
  5165                              <1> ;	and	ecx, 3fh
  5166                              <1> ;	xchg	dl, dh
  5167                              <1> ;	shr	dh, 6
  5168                              <1> ;		; DX = cylinder (0 to 1023)
  5169                              <1> ;	;mul 	dx
  5170                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder
  5171                              <1> ;	mul	edx
  5172                              <1> ;	dec	cl  ; sector - 1
  5173                              <1> ;	;add	ax, cx
  5174                              <1> ;	;adc	dx, 0
  5175                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  5176                              <1> ;	add	eax, ecx
  5177                              <1> ;	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5178                              <1> ;	; 24/12/2021
  5179                              <1> ;	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  5180                              <1> ;	;push	dx
  5181                              <1> ;	;push	ax
  5182                              <1> ;	push	eax
  5183                              <1> ;	mov	al, [ebx+14]  ; sectors per track (logical)	
  5184                              <1> ;	mul	ch
  5185                              <1> ;		; AX = Head * Sectors/Track
  5186                              <1> ;	cwd
  5187                              <1> ;	;pop	dx
  5188                              <1> ;	pop	edx
  5189                              <1> ;	;add	ax, dx
  5190                              <1> ;	;pop	dx
  5191                              <1> ;	;adc	dx, 0 ; add carry bit
  5192                              <1> ;	add	eax, edx
  5193                              <1> ;
  5194                              <1> ;lbarw2:
  5195                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5196                              <1> 	
  5197 0000211A 29D2                <1> 	sub	edx, edx ; 21/02/2015
  5198                              <1> 	
  5199                              <1> 	; 11/07/2022
  5200                              <1> 	;mov	dl, cl ; 21/02/2015
  5201                              <1>         
  5202 0000211C C645F800            <1> 	mov     byte [CMD_BLOCK], 0 ; Features Register
  5203                              <1> 				; NOTE: Features register (1F1h, 171h)
  5204                              <1> 				; is not used for ATA device R/W functions. 
  5205                              <1> 				; It is old/obsolete 'write precompensation'
  5206                              <1> 				; register and error register
  5207                              <1> 				; for old ATA/IDE devices.
  5208                              <1> 	; 18/01/2014
  5209                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  5210 00002120 8A0D[46630000]      <1> 	mov	cl, [hf_m_s]
  5211                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  5212                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  5213                              <1> 				; bit 6 = 1 = LBA mode
  5214                              <1> 				; bit 7 = 1
  5215 00002126 80C90E              <1> 	or	cl, 0Eh ; 1110b
  5216                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  5217 00002129 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  5218 0000212E C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  5219                              <1> 	;or	dh, ch
  5220 00002131 09C8                <1> 	or	eax, ecx	
  5221                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  5222                              <1> 				  ; (Sector Number Register)
  5223                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  5224                              <1> 				  ; (Cylinder Low Register)
  5225                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  5226                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  5227                              <1> 				  ; (Cylinder High Register)
  5228                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  5229                              <1> 				  ; (Drive/Head Register)
  5230                              <1> 	
  5231                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  5232 00002133 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  5233                              <1> 	;14/02/2015
  5234                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  5235 00002136 EB3E                <1> 	jmp	short su4
  5236                              <1> su3:
  5237                              <1> 	; 02/02/2015 
  5238                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  5239                              <1> 	;cmp 	ah, 14h
  5240                              <1> 	;jna 	short chsfnc
  5241                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5242                              <1> 	;cmp	ah, 2
  5243                              <1> 	;jna	short chsfnc
  5244                              <1> 	; 11/07/2022 
  5245                              <1> 	; (al = function, read = 1 or write = 2)
  5246 00002138 3C02                <1> 	cmp	al, 2 
  5247 0000213A 760B                <1> 	jna	short chsfnc
  5248                              <1> invldfnc:
  5249                              <1>         ; 14/02/2015  
  5250                              <1> 	;pop	es ; **
  5251                              <1>         ;pop	ax ; ***
  5252                              <1>         ; 24/12/2021
  5253 0000213C 58                  <1> 	pop	eax ; ***
  5254                              <1> 	;;jmp	short BAD_COMMAND_POP
  5255                              <1> 	; 11/07/2022
  5256                              <1>         ;jmp     short BAD_COMMAND
  5257                              <1> 
  5258                              <1> 	; 11/07/2022
  5259                              <1> BAD_COMMAND:
  5260 0000213D C605[BB680000]01    <1> 	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5261                              <1> 	;mov	al, 0
  5262 00002144 28C0                <1> 	sub	al, al ; 0
  5263 00002146 C3                  <1> 	retn
  5264                              <1> 
  5265                              <1> chsfnc:	
  5266 00002147 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5267 0000214B 66C1E802            <1> 	shr	ax, 2
  5268 0000214F 8845F8              <1> 	mov	[CMD_BLOCK], al
  5269                              <1> 	;
  5270                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5271                              <1> 	;;push	edx ; *
  5272                              <1> 	;;mov	dx, [HF_REG_PORT]
  5273                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5274                              <1> 	;;pop	edx ; * 
  5275                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5276                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5277                              <1> 	;;or	ah, al
  5278                              <1> 	;;mov	[CONTROL_BYTE], ah
  5279                              <1> 	;
  5280 00002152 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5281 00002154 243F                <1> 	and	al, 3Fh
  5282 00002156 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5283 00002159 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5284 0000215C 88C8                <1> 	mov	al, cl
  5285 0000215E C0E806              <1> 	shr	al, 6
  5286 00002161 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5287                              <1> 	;;05/01/2015
  5288                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5289 00002164 A0[46630000]        <1> 	mov	al, [hf_m_s]
  5290 00002169 C0E004              <1> 	shl	al, 4
  5291 0000216C 80E60F              <1> 	and	dh, 0Fh			; HEAD NUMBER
  5292 0000216F 08F0                <1> 	or	al, dh
  5293 00002171 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5294 00002173 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5295                              <1> su4:
  5296                              <1> 	;; 14/02/2015
  5297                              <1>         ;;pop	ax
  5298                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5299                              <1>         ;;push	ax
  5300                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5301                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5302                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5303                              <1> 	;pop	ax ; ***
  5304                              <1> 	; 24/12/2021
  5305 00002176 58                  <1> 	pop	eax ; *** ; function (in AL) ; 11/07/2022
  5306                              <1> 	
  5307                              <1> 	;mov	[CMD_BLOCK+1], al
  5308 00002177 C645F901            <1>         mov	byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w)
  5309                              <1> 
  5310                              <1> 	; 11/07/2022
  5311                              <1> 	;mov	ebx, esi
  5312                              <1> 	; (esi = buffer address)	
  5313                              <1> 
  5314 0000217B 3C02                <1> 	cmp	al, 2
  5315 0000217D 7433                <1> 	je	short DISK_WRITE
  5316                              <1> 
  5317                              <1> 	;jmp	short DISK_READ
  5318                              <1> 
  5319                              <1> ;	;xor	ebx, ebx
  5320                              <1> ;	;mov	bl, ah
  5321                              <1> ;
  5322                              <1> ;       ;xor	bh, bh
  5323                              <1> ;       ;sal	bx, 1
  5324                              <1> ;       sal	bx, 2	; 32 bit offset (21/02/2015)
  5325                              <1> ;	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5326                              <1> ;       ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5327                              <1> ;       ;;jnb	short BAD_COMMAND_POP
  5328                              <1> ;   	; 08/07/2022
  5329                              <1> ;	;cmp	ebx, M1L
  5330                              <1> ;	;jnb	short BAD_COMMAND
  5331                              <1> ;
  5332                              <1> ;	xchg	ebx, esi
  5333                              <1> ;
  5334                              <1> ;	;;;pop	ax			; RESTORE AX
  5335                              <1> ;	;;;pop	bx			; AND DATA ADDRESS
  5336                              <1> ;	
  5337                              <1> ;	;;push	cx
  5338                              <1> ;	;;push	ax			; ADJUST ES:BX
  5339                              <1> ;	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5340                              <1> ;	;shr	cx, 4
  5341                              <1> ;	;mov	ax, es
  5342                              <1> ;	;add	ax, cx
  5343                              <1> ;	;mov	es, ax
  5344                              <1> ;	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5345                              <1> ;	;;pop	ax
  5346                              <1> ;	;;pop	cx
  5347                              <1> ;
  5348                              <1> ;	jmp	dword [esi+M1]
  5349                              <1> 
  5350                              <1> ;;BAD_COMMAND_POP:
  5351                              <1> ;;	pop	ax
  5352                              <1> ;;	pop	bx
  5353                              <1> ;
  5354                              <1> ;	; 11/07/2022
  5355                              <1> ;BAD_COMMAND:
  5356                              <1> ;	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5357                              <1> ;	;mov	al, 0
  5358                              <1> ;	sub	al, al ; 0
  5359                              <1> ;	retn
  5360                              <1> 
  5361                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5362                              <1> 
  5363                              <1> ;----------------------------------------
  5364                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5365                              <1> ;----------------------------------------
  5366                              <1> ; 
  5367                              <1> DISK_READ:
  5368 0000217F C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5369                              <1>         ;jmp	COMMANDI
  5370                              <1> 
  5371                              <1> ; 16/07/2022
  5372                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5373                              <1> 
  5374                              <1> ;----------------------------------------
  5375                              <1> ; COMMANDI				:
  5376                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5377                              <1> ;	NSECTOR RETURNS ZERO		:
  5378                              <1> ;----------------------------------------
  5379                              <1> COMMANDI:
  5380                              <1> 	; 11/07/2022 
  5381                              <1> 	;	(check 64K boundary is not needed)
  5382                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5383                              <1> 	;jc	short CMD_ABORT
  5384                              <1> 	
  5385                              <1> 	;mov	di, bx
  5386                              <1> 	; 11/07/2022
  5387                              <1> 	; (esi = buffer address)
  5388                              <1> 	;mov	edi, ebx ; 21/02/2015
  5389 00002183 89F7                <1> 	mov	edi, esi ; 11/07/2022	
  5390                              <1> 
  5391 00002185 E8AE010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5392 0000218A 7525                <1> 	jnz	short CMD_ABORT
  5393                              <1> CMD_I1:
  5394 0000218C E819020000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5395 00002191 751E                <1> 	jnz	short TM_OUT		; TIME OUT
  5396                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5397                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5398 00002193 29C9                <1> 	sub	ecx, ecx
  5399 00002195 FEC5                <1> 	inc	ch
  5400                              <1> 	; ecx = 256
  5401                              <1> 	;mov	dx, HF_PORT
  5402 00002197 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5403 0000219E FA                  <1> 	cli
  5404 0000219F FC                  <1> 	cld
  5405 000021A0 F3666D              <1> 	rep	insw			; GET THE SECTOR
  5406 000021A3 FB                  <1> 	sti
  5407                              <1> 	
  5408                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5409                              <1> 	;jz	short CMD_I3
  5410                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5411                              <1> 	;jc	short TM_OUT
  5412                              <1> 	;;mov	dx, HF_PORT
  5413                              <1> 	;mov	dx,[HF_PORT]
  5414                              <1> 	;xor	ecx, ecx	
  5415                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5416                              <1> 	;mov	cl, 4
  5417                              <1> ;CMD_I2: 
  5418                              <1> 	;inc	al, dx
  5419                              <1> 	;mov 	[edi], al ; 21/02/2015
  5420                              <1> 	;inc	edi
  5421                              <1> 	;loop	CMD_I2
  5422                              <1> CMD_I3:
  5423                              <1> 	; 16/07/2022
  5424                              <1> 	; wait for 400 ns
  5425 000021A4 80C207              <1> 	add 	dl, 7
  5426 000021A7 EC                  <1> 	in	al, dx
  5427 000021A8 EC                  <1> 	in	al, dx
  5428 000021A9 EC                  <1> 	in	al, dx
  5429                              <1> 	;
  5430 000021AA E817010000          <1> 	call	CHECK_STATUS
  5431 000021AF 7500                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5432                              <1> 	; 11/07/2022
  5433                              <1> 	; (sector count = 1)
  5434                              <1> 	;dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5435                              <1> 	;jnz	SHORT CMD_I1
  5436                              <1> CMD_ABORT:
  5437                              <1> TM_OUT: 
  5438 000021B1 C3                  <1> 	retn
  5439                              <1> 
  5440                              <1> ;---------------------------------------------------
  5441                              <1> 
  5442                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5443                              <1> 
  5444                              <1> ;----------------------------------------
  5445                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5446                              <1> ;----------------------------------------
  5447                              <1> 
  5448                              <1> DISK_WRITE:
  5449 000021B2 C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5450                              <1>         ;JMP	COMMANDO
  5451                              <1> 
  5452                              <1> ; 16/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  5453                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5454                              <1> 
  5455                              <1> ;----------------------------------------
  5456                              <1> ; COMMANDO				:
  5457                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5458                              <1> ;	NSECTOR RETURNS ZERO		:
  5459                              <1> ;----------------------------------------
  5460                              <1> COMMANDO:
  5461                              <1> 	; 11/07/2022 
  5462                              <1> 	;	(check 64K boundary is not needed)
  5463                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5464                              <1> 	;jc	short CMD_ABORT
  5465                              <1> CMD_OF:
  5466                              <1> 	; 11/07/2022
  5467                              <1> 	; (esi = ebx = buffer address)
  5468                              <1> 	;mov	esi, ebx ; 21/02/2015
  5469 000021B6 E87D010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5470 000021BB 75F4                <1> 	jnz	short CMD_ABORT
  5471 000021BD E83F020000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5472 000021C2 72ED                <1> 	jc	short TM_OUT		; TOO LONG
  5473                              <1> CMD_O1:
  5474                              <1> 	; 16/07/2022
  5475 000021C4 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5476                              <1> 
  5477                              <1> 	; 10/07/2022
  5478                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5479 000021CB 31C9                <1> 	xor	ecx, ecx
  5480 000021CD FEC5                <1> 	inc	ch
  5481                              <1> 	; ecx = 256
  5482 000021CF FA                  <1> 	cli
  5483 000021D0 FC                  <1> 	cld
  5484 000021D1 F3666F              <1> 	rep	outsw
  5485 000021D4 FB                  <1> 	sti
  5486                              <1> 
  5487                              <1> 	; 10/07/2022
  5488                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5489                              <1> 	;jz	short CMD_O3
  5490                              <1> 	;
  5491                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5492                              <1> 	;jc	short TM_OUT
  5493                              <1> 	;;mov	dx, HF_PORT
  5494                              <1> 	;mov	dx, [HF_PORT]
  5495                              <1> 	;sub	ecx, ecx	
  5496                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5497                              <1> 	;mov	cl, 4
  5498                              <1> ;CMD_O2:
  5499                              <1> 	;;lodsb
  5500                              <1> 	;mov	al, [esi]
  5501                              <1> 	;out	dx, al
  5502                              <1> 	;inc	esi
  5503                              <1> 	;loop	CMD_O2
  5504                              <1> 
  5505                              <1> CMD_O3:
  5506 000021D5 E8D0010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5507 000021DA 75D5                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5508 000021DC E8E5000000          <1> 	call	CHECK_STATUS
  5509 000021E1 75CE                <1> 	jnz	short CMD_ABORT
  5510                              <1> 
  5511                              <1> 	; 11/07/2022
  5512                              <1> 	; (sector count = 1)
  5513                              <1> 	;test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5514                              <1> 	;jnz	short CMD_O1
  5515                              <1> 	
  5516                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5517 000021E3 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5518 000021EA 80C202              <1> 	add	dl, 2
  5519                              <1> 	;inc	dl
  5520                              <1> 	;inc	dl
  5521 000021ED EC                  <1> 	in	al, dx			;
  5522 000021EE A8FF                <1> 	test	al, 0FFh 		;
  5523 000021F0 7407                <1> 	jz	short CMD_O4		; COUNT = 0  OK
  5524 000021F2 C605[BB680000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5525                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5526                              <1> CMD_O4:
  5527 000021F9 C3                  <1> 	retn
  5528                              <1> 
  5529                              <1> ; 10/07/2022
  5530                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5531                              <1> 
  5532                              <1> ;----------------------------------------
  5533                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5534                              <1> ;----------------------------------------
  5535                              <1> 
  5536                              <1> ; 18-1-2015 : one controller reset (not other one)
  5537                              <1> 
  5538                              <1> DISK_RESET:
  5539 000021FA FA                  <1> 	cli
  5540 000021FB E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5541                              <1> 	;JMP	$+2
  5542                              <1> 	IODELAY
  2170 000021FD EB00                <2>  jmp short $+2
  2171 000021FF EB00                <2>  jmp short $+2
  5543                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5544 00002201 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5545 00002203 E6A1                <1> 	out	INTB01, al
  5546 00002205 FB                  <1> 	sti				; START INTERRUPTS
  5547                              <1> 	; 14/02/2015
  5548                              <1> 	;mov	di, dx
  5549                              <1> 	; 24/12/2021
  5550 00002206 89D7                <1> 	mov	edi, edx	
  5551                              <1> 	; 04/01/2015
  5552                              <1> 	;xor	di,di
  5553                              <1> drst0:
  5554 00002208 B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5555                              <1> 	;mov	dx, HF_REG_PORT
  5556 0000220A 668B15[44630000]    <1> 	mov	dx, [HF_REG_PORT]
  5557 00002211 EE                  <1> 	out	dx, al			; RESET
  5558                              <1> ;	mov	cx, 10			; DELAY COUNT
  5559                              <1> ;DRD:	dec	cx
  5560                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5561                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5562                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5563                              <1> 	; 10/07/2022
  5564 00002212 29C9                <1> 	sub	ecx, ecx
  5565 00002214 B102                <1> 	mov	cl, 2
  5566 00002216 E87DF2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5567                              <1>                                         ; 40 micro seconds)
  5568 0000221B A0[BD680000]        <1> 	mov	al, [CONTROL_BYTE]
  5569 00002220 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5570 00002222 EE                  <1> 	out	dx, al			; TURN RESET OFF
  5571 00002223 E8B2010000          <1> 	call	NOT_BUSY
  5572 00002228 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5573 0000222A 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5574 00002231 FEC2                <1> 	inc	dl  ; HF_PORT+1
  5575                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5576                              <1>         ;mov	cl, 10
  5577                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5578                              <1> 	; 10/07/2022
  5579                              <1> 	;xor	ecx, ecx
  5580 00002233 B10A                <1> 	mov	cl, 10 
  5581                              <1> drst1:
  5582 00002235 EC                  <1> 	in	al, dx			; GET RESET STATUS
  5583 00002236 3C01                <1> 	cmp	al, 1
  5584                              <1> 	; 04/01/2015
  5585 00002238 740C                <1> 	jz	short drst2
  5586                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5587                              <1>         	; Drive/Head Register - bit 4
  5588                              <1> 	;loop	drst1
  5589                              <1> 	; 10/07/2022
  5590 0000223A FEC9                <1> 	dec	cl
  5591 0000223C 75F7                <1> 	jnz	short drst1
  5592                              <1> DRERR:	
  5593 0000223E C605[BB680000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5594 00002245 C3                  <1> 	retn
  5595                              <1> drst2:
  5596                              <1> 	; 14/02/2015
  5597                              <1> 	;mov	dx, di
  5598                              <1> 	; 24/12/2021
  5599 00002246 89FA                <1> 	mov	edx, edi
  5600                              <1> ;drst3:
  5601                              <1> ;	; 05/01/2015
  5602                              <1> ;	shl 	di, 1
  5603                              <1> ;	; 04/01/2015
  5604                              <1> ;	mov	ax, [di+hd_cports]
  5605                              <1> ;	cmp	ax, [HF_REG_PORT]
  5606                              <1> ;	je	short drst4
  5607                              <1> ;	mov	[HF_REG_PORT], ax
  5608                              <1> ;	; 03/01/2015
  5609                              <1> ;	mov	ax, [di+hd_ports]
  5610                              <1> ;       mov     [HF_PORT], ax
  5611                              <1> ;	; 05/01/2014
  5612                              <1> ;	shr	di, 1
  5613                              <1> ;	; 04/01/2015
  5614                              <1> ;	jmp	short drst0	; reset other controller
  5615                              <1> ;drst4:
  5616                              <1> ;	; 05/01/2015
  5617                              <1> ;	shr	di, 1
  5618                              <1> ;	mov	al, [di+hd_dregs]
  5619                              <1> ;	and	al, 10h ; bit 4 only
  5620                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5621                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5622                              <1> 	;
  5623 00002248 A0[46630000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5624 0000224D A801                <1> 	test	al, 1
  5625                              <1> 	;jnz	short drst6
  5626 0000224F 7516                <1>         jnz     short drst4
  5627 00002251 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5628                              <1> ;drst5:
  5629                              <1> drst3:
  5630 00002255 E813000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5631                              <1> 	;mov	dx, di
  5632 0000225A E8A3000000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5633                              <1> 	; 04/01/2014
  5634                              <1> ;	inc	di
  5635                              <1> ;	mov	dx, di
  5636                              <1> ;	cmp	dl, [HF_NUM]
  5637                              <1> ;	jb	short drst3
  5638                              <1> ;DRE:
  5639 0000225F C605[BB680000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5640 00002266 C3                  <1> 	retn
  5641                              <1> ;drst6:
  5642                              <1> drst4:		; Drive/Head Register - bit 4
  5643 00002267 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5644                              <1>         ;jmp    short drst5
  5645 0000226B EBE8                <1>         jmp     short drst3
  5646                              <1> 
  5647                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5648                              <1> 
  5649                              <1> ;----------------------------------------
  5650                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5651                              <1> ;----------------------------------------
  5652                              <1> 	; 03/01/2015
  5653                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5654                              <1> 	; logical sector per logical track
  5655                              <1> 	; and logical heads - 1 would be set but
  5656                              <1> 	; it is seen as it will be good
  5657                              <1> 	; if physical parameters will be set here
  5658                              <1> 	; because, number of heads <= 16.
  5659                              <1> 	; (logical heads usually more than 16)
  5660                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5661                              <1> 	;	== INT 13h physical parameters
  5662                              <1> 
  5663                              <1> ;INIT_DRV:
  5664                              <1> ;	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5665                              <1> ;	call	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5666                              <1> ;	mov	al, [es:bx+2]		; GET NUMBER OF HEADS
  5667                              <1> ;	dec	al			; CONVERT TO 0-INDEX
  5668                              <1> ;	mov	ah, [CMD_BLOCK+5] 	; GET SDH REGISTER
  5669                              <1> ;	and	ah, 0F0h 		; CHANGE HEAD NUMBER
  5670                              <1> ;	or	ah, al			; TO MAX HEAD
  5671                              <1> ;	mov	[CMD_BLOCK+5], ah
  5672                              <1> ;	mov	al, [es:bx+14]		; MAX SECTOR NUMBER
  5673                              <1> ;	mov	[CMD_BLOCK+1], al
  5674                              <1> ;	sub	ax, ax
  5675                              <1> ;	mov	[CMD_BLOCK+3], al 	; ZERO FLAGS
  5676                              <1> ;	call	COMMAND 		; TELL CONTROLLER
  5677                              <1> ;	jnz	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5678                              <1> ;	call	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5679                              <1> ;	jnz	short INIT_EXIT		; TIME OUT
  5680                              <1> ;	call	CHECK_STATUS
  5681                              <1> ;INIT_EXIT:
  5682                              <1> ;	retn
  5683                              <1> 
  5684                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5685                              <1> 
  5686                              <1> ; 04/01/2015
  5687                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5688                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5689                              <1> INIT_DRV:
  5690                              <1> 	;xor	ah, ah
  5691 0000226D 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5692 0000226F B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5693 00002271 3825[D0680000]      <1>         cmp     [LBAMode], ah   ; 0
  5694 00002277 7702                <1> 	ja	short idrv0
  5695 00002279 B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5696                              <1> idrv0:
  5697                              <1> 	; DL = drive number (0 based)
  5698 0000227B E80D020000          <1> 	call	GET_VEC
  5699                              <1> 	;push	bx
  5700 00002280 53                  <1> 	push	ebx ; 21/02/2015
  5701                              <1> 	;add	bx, ax
  5702 00002281 01C3                <1> 	add	ebx, eax
  5703                              <1> 	;; 05/01/2015
  5704 00002283 8A25[46630000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5705                              <1> 	;;and 	ah, 1 
  5706 00002289 C0E404              <1> 	shl	ah, 4
  5707 0000228C 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5708                              <1> 	;mov	al, [es:bx]
  5709 0000228F 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5710 00002291 FEC8                <1> 	dec	al	 ; last head number 
  5711                              <1> 	;and	al, 0Fh
  5712 00002293 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5713                              <1> 	;
  5714 00002295 C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5715 00002299 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5716                              <1> 	;pop	bx
  5717 0000229C 5B                  <1> 	pop	ebx
  5718 0000229D 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5719 0000229F B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5720 000022A1 803D[D0680000]00    <1> 	cmp	byte [LBAMode], 0
  5721 000022A8 7702                <1> 	ja	short idrv1
  5722 000022AA B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5723                              <1> idrv1:
  5724                              <1> 	;xor	ah, ah
  5725                              <1> 	;add	bx, ax
  5726 000022AC 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5727                              <1> 	;mov	al, [es:bx]
  5728                              <1> 			; sector number
  5729 000022AE 8A03                <1> 	mov	al, [ebx]
  5730 000022B0 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5731 000022B3 28C0                <1> 	sub	al, al
  5732 000022B5 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5733 000022B8 E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5734 000022BD 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5735 000022BF E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5736 000022C4 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5737                              <1> 	;call	CHECK_STATUS
  5738                              <1> 	;jmp	short CHECK_STATUS
  5739                              <1> ;INIT_EXIT:
  5740                              <1> 	;retn
  5741                              <1> 
  5742                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5743                              <1> 
  5744                              <1> ;----------------------------------------
  5745                              <1> ;	CHECK FIXED DISK STATUS 	:
  5746                              <1> ;----------------------------------------
  5747                              <1> CHECK_STATUS:
  5748 000022C6 E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5749                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5750                              <1> 	; 10/07/2022
  5751 000022CB 7510                <1> 	jnz	short CHECK_S2
  5752 000022CD A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5753 000022CF 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5754 000022D1 E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5755                              <1> CHECK_S1:
  5756 000022D6 803D[BB680000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5757                              <1> CHECK_S2:
  5758                              <1> INIT_EXIT:	; 10/07/2022
  5759 000022DD C3                  <1> 	retn
  5760                              <1> 
  5761                              <1> ;----------------------------------------
  5762                              <1> ;	TEST DISK READY      (AH = 10H) :
  5763                              <1> ;----------------------------------------
  5764                              <1> 
  5765                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5766 000022DE E8F7000000          <1> 	call	NOT_BUSY
  5767 000022E3 751C                <1> 	jnz	short TR_EX
  5768 000022E5 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5769 000022E8 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5770 000022EF 80C206              <1> 	add	dl, 6
  5771 000022F2 EE                  <1> 	out	dx, al
  5772 000022F3 E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5773 000022F8 7507                <1> 	jnz	short TR_EX
  5774 000022FA C605[BB680000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5775                              <1> TR_EX:	
  5776 00002301 C3                  <1> 	retn
  5777                              <1> 
  5778                              <1> ;----------------------------------------
  5779                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5780                              <1> ;----------------------------------------
  5781                              <1> 
  5782                              <1> HDISK_RECAL:
  5783 00002302 C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5784 00002306 E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5785 0000230B 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5786 0000230D E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5787 00002312 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5788 00002314 E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5789 00002319 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5790                              <1> RECAL_X:
  5791 0000231B E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5792 00002320 803D[BB680000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5793 00002327 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5794 00002329 C605[BB680000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5795                              <1> RECAL_EXIT:
  5796 00002330 803D[BB680000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5797 00002337 C3                  <1> 	retn
  5798                              <1> 
  5799                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5800                              <1> 
  5801                              <1> ;--------------------------------------------------------
  5802                              <1> ; COMMAND						:
  5803                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5804                              <1> ; OUTPUT						:
  5805                              <1> ;	BL = STATUS					:
  5806                              <1> ;	BH = ERROR REGISTER				:
  5807                              <1> ;--------------------------------------------------------
  5808                              <1> 
  5809                              <1> COMMAND:
  5810                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5811                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5812                              <1> COMMAND1:
  5813                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5814 00002338 E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5815                              <1> 	;;pop	ecx
  5816                              <1> 	;pop	ebx ; 10/07/2022
  5817 0000233D 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5818 0000233F 803D[BB680000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5819                              <1> 	;jz	short CMD_TIMEOUT
  5820                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5821                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5822 00002346 7507                <1> 	jne	short COMMAND4
  5823                              <1> CMD_TIMEOUT:
  5824 00002348 C605[BB680000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5825                              <1> COMMAND4:
  5826                              <1> 	;;pop	ebx ; 10/07/2022
  5827 0000234F 803D[BB680000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5828 00002356 C3                  <1> 	retn
  5829                              <1> COMMAND2:
  5830                              <1> 	;;pop	ebx ; 10/07/2022
  5831                              <1> 	;push	edi ; 10/07/2022
  5832 00002357 C605[B6680000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5833 0000235E FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5834 0000235F E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5835                              <1> 	;and	al, 0BFh
  5836 00002361 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5837                              <1> 	;JMP	$+2
  5838                              <1> 	IODELAY
  2170 00002363 EB00                <2>  jmp short $+2
  2171 00002365 EB00                <2>  jmp short $+2
  5839 00002367 E6A1                <1> 	out	INTB01, al
  5840 00002369 E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5841 0000236B 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5842                              <1> 	;JMP	$+2
  5843                              <1> 	IODELAY
  2170 0000236D EB00                <2>  jmp short $+2
  2171 0000236F EB00                <2>  jmp short $+2
  5844 00002371 E621                <1> 	out	INTA01, al
  5845 00002373 FB                  <1> 	sti
  5846                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5847                              <1> 	; 10/07/2022
  5848 00002374 31C9                <1> 	xor	ecx, ecx
  5849                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5850 00002376 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5851 0000237D FEC2                <1> 	inc	dl
  5852 0000237F F605[BD680000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5853 00002386 7411                <1> 	jz	short COMMAND3
  5854 00002388 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5855 0000238B 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5856 0000238D 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5857 0000238F 7208                <1> 	jb	short COMMAND3
  5858 00002391 3C40                <1> 	cmp	al, 40h
  5859 00002393 7704                <1> 	ja	short COMMAND3
  5860 00002395 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5861                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5862                              <1> COMMAND3:
  5863                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5864                              <1> 	; 10/07/2022
  5865 00002399 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5866 0000239D EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5867                              <1> 	IODELAY
  2170 0000239E EB00                <2>  jmp short $+2
  2171 000023A0 EB00                <2>  jmp short $+2
  5868                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5869                              <1> 	; 10/07/2022
  5870 000023A2 41                  <1> 	inc	ecx
  5871                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5872 000023A3 42                  <1> 	inc	edx   ; 10/07/2022	
  5873                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5874                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5875 000023A4 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5876 000023A7 72F0                <1> 	jb	short COMMAND3
  5877                              <1> 	;pop	edi ; 10/07/2022
  5878 000023A9 C3                  <1> 	retn				; ZERO FLAG IS SET
  5879                              <1> 
  5880                              <1> ;CMD_TIMEOUT:
  5881                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5882                              <1> ;COMMAND4:
  5883                              <1> ;	pop	ebx
  5884                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5885                              <1> ;	retn
  5886                              <1> 
  5887                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5888                              <1> 
  5889                              <1> ;----------------------------------------
  5890                              <1> ;	WAIT FOR INTERRUPT		:
  5891                              <1> ;----------------------------------------
  5892                              <1> ;WAIT:
  5893                              <1> _WAIT:
  5894 000023AA FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5895                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5896                              <1> 	;clc
  5897                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5898                              <1> 	;int	15h
  5899                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5900                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5901                              <1> 
  5902                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5903                              <1> 	;; 21/02/2015
  5904                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5905                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5906 000023AB B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5907                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5908                              <1> ;-----	WAIT LOOP
  5909                              <1> 
  5910                              <1> WT1:	
  5911                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5912 000023B0 F605[B6680000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5913                              <1> 	;loopz	WT1
  5914 000023B7 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5915                              <1> 	;dec	bl
  5916                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5917                              <1> 
  5918                              <1> WT1_hi:
  5919 000023B9 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5920 000023BB A810                <1> 	test	al, 10h			; transition on memory
  5921 000023BD 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5922                              <1> WT1_lo:
  5923 000023BF E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5924 000023C1 A810                <1> 	test	al, 10h			
  5925 000023C3 74FA                <1> 	jz	short WT1_lo
  5926 000023C5 E2E9                <1> 	loop	WT1
  5927                              <1> 	;;or	bl, bl
  5928                              <1> 	;;jz	short WT2	
  5929                              <1> 	;;dec	bl
  5930                              <1> 	;;jmp	short WT1
  5931                              <1> 	;dec	bl
  5932                              <1> 	;jnz	short WT1	
  5933                              <1> WT2:	
  5934                              <1> 	; 10/07/2022
  5935                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5936 000023C7 B080                <1> 	mov	al, TIME_OUT
  5937 000023C9 EB07                <1> 	jmp	short WT4
  5938                              <1> WT3:
  5939                              <1> 	;mov	byte [DISK_STATUS1], 0
  5940                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5941 000023CB 28C0                <1> 	sub	al, al ; 0
  5942 000023CD A2[B6680000]        <1> 	mov	byte [HF_INT_FLAG], al
  5943                              <1> WT4:
  5944                              <1> NB2:	
  5945 000023D2 A2[BB680000]        <1> 	mov	byte [DISK_STATUS1], al
  5946                              <1> 
  5947                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5948 000023D7 20C0                <1> 	and	al, al
  5949                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5950 000023D9 C3                  <1> 	retn
  5951                              <1> 
  5952                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5953                              <1> 
  5954                              <1> ;----------------------------------------
  5955                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5956                              <1> ;----------------------------------------
  5957                              <1> NOT_BUSY:
  5958 000023DA FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5959                              <1> 	;push	ebx
  5960                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5961 000023DB 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  5962 000023E2 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  5963                              <1> 	;mov	bl, DELAY_1
  5964                              <1> 					; wait for 10 seconds
  5965                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  5966                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  5967                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  5968 000023E5 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  5969                              <1> 	;
  5970                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  5971                              <1> NB1:	
  5972 000023EA EC                  <1> 	in	al, dx			; CHECK STATUS
  5973                              <1> 	;test	al, ST_BUSY
  5974 000023EB 2480                <1> 	and	al, ST_BUSY
  5975                              <1> 	;loopnz NB1
  5976 000023ED 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  5977                              <1> 	;dec	bl			
  5978                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  5979                              <1> 
  5980                              <1> NB1_hi: 
  5981 000023EF E461                <1> 	in	al, SYS1		; wait for hi to lo
  5982 000023F1 A810                <1> 	test	al, 010h		; transition on memory
  5983 000023F3 75FA                <1> 	jnz	short NB1_hi		; refresh.
  5984                              <1> NB1_lo: 
  5985 000023F5 E461                <1> 	in	al, SYS1
  5986 000023F7 A810                <1> 	test	al, 010h
  5987 000023F9 74FA                <1> 	jz	short NB1_lo
  5988 000023FB E2ED                <1> 	loop	NB1
  5989                              <1> 	;dec	bl
  5990                              <1> 	;jnz	short NB1
  5991                              <1> 	;
  5992                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  5993                              <1> 	;;jb	short NB1
  5994                              <1> 	;
  5995                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5996                              <1> 	;jmp	short NB3
  5997 000023FD B080                <1> 	mov	al, TIME_OUT
  5998                              <1> ;NB2:	
  5999 000023FF EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  6000                              <1> 
  6001                              <1> ;	;mov	byte [DISK_STATUS1], 0
  6002                              <1> ;;NB3:	
  6003                              <1> ;	;pop	ebx
  6004                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  6005                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  6006                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  6007                              <1> ;	retn
  6008                              <1> 
  6009                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6010                              <1> 
  6011                              <1> ;----------------------------------------
  6012                              <1> ;	WAIT FOR DATA REQUEST		:
  6013                              <1> ;----------------------------------------
  6014                              <1> WAIT_DRQ:
  6015                              <1> 	;mov	cx, DELAY_3
  6016                              <1> 	;mov	dx, HF_PORT+7
  6017 00002401 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  6018 00002408 80C207              <1> 	add	dl, 7
  6019                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  6020                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  6021                              <1> 					; (but it is written as 2000
  6022                              <1> 					; micro seconds in ATORGS.ASM file
  6023                              <1> 					; of Award Bios - 1999, D1A0622)
  6024 0000240B B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6025                              <1> WQ_1:
  6026 00002410 EC                  <1> 	in	al, dx			; GET STATUS
  6027 00002411 A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  6028 00002413 7516                <1> 	jnz	short WQ_OK
  6029                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6030                              <1> WQ_hi:	
  6031 00002415 E461                <1> 	in	al, SYS1		; wait for hi to lo
  6032 00002417 A810                <1> 	test	al, 010h		; transition on memory
  6033 00002419 75FA                <1> 	jnz	short WQ_hi		; refresh.
  6034                              <1> WQ_lo:  
  6035 0000241B E461                <1> 	in	al, SYS1
  6036 0000241D A810                <1> 	test	al, 010h
  6037 0000241F 74FA                <1> 	jz	short WQ_lo
  6038 00002421 E2ED                <1> 	loop	WQ_1
  6039                              <1> 
  6040 00002423 C605[BB680000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  6041 0000242A F9                  <1> 	stc
  6042                              <1> WQ_OK:
  6043 0000242B C3                  <1> 	retn
  6044                              <1> ;WQ_OK:
  6045                              <1> 	;clc
  6046                              <1> 	;retn
  6047                              <1> 
  6048                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6049                              <1> 
  6050                              <1> ;----------------------------------------
  6051                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  6052                              <1> ;----------------------------------------
  6053                              <1> CHECK_ST:
  6054                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  6055 0000242C 668B15[42630000]    <1> 	mov	dx, [HF_PORT]
  6056 00002433 80C207              <1> 	add	dl, 7
  6057 00002436 EC                  <1> 	in	al, dx
  6058 00002437 A2[B5680000]        <1> 	mov	[HF_STATUS], al
  6059                              <1> 	;mov	ah, 0
  6060 0000243C 28E4                <1> 	sub	ah, ah ; 0
  6061 0000243E A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  6062 00002440 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  6063 00002442 B4CC                <1> 	mov	ah, WRITE_FAULT
  6064 00002444 A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  6065 00002446 7514                <1> 	jnz	short CKST_EXIT
  6066 00002448 B4AA                <1> 	mov	ah, NOT_RDY
  6067 0000244A A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  6068 0000244C 740E                <1> 	jz	short CKST_EXIT
  6069 0000244E B440                <1> 	mov	ah, BAD_SEEK
  6070 00002450 A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  6071 00002452 7408                <1> 	jz	short CKST_EXIT
  6072 00002454 B411                <1> 	mov	ah, DATA_CORRECTED
  6073 00002456 A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  6074 00002458 7502                <1> 	jnz	short CKST_EXIT
  6075                              <1> 	;mov	ah, 0
  6076 0000245A 30E4                <1> 	xor	ah, ah ; 0
  6077                              <1> CKST_EXIT:
  6078 0000245C 8825[BB680000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  6079 00002462 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  6080 00002465 7402                <1> 	je	short CKST_EX1
  6081                              <1> 	;cmp	ah, 0
  6082 00002467 20E4                <1> 	and	ah, ah
  6083                              <1> CKST_EX1:
  6084 00002469 C3                  <1> 	retn
  6085                              <1> 
  6086                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6087                              <1> 
  6088                              <1> ;----------------------------------------
  6089                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  6090                              <1> ;----------------------------------------
  6091                              <1> CHECK_ER:
  6092                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  6093 0000246A 668B15[42630000]    <1> 	mov	dx, [HF_PORT]		;
  6094 00002471 FEC2                <1> 	inc	dl
  6095 00002473 EC                  <1> 	in	al, dx
  6096                              <1> 	; 10/07/2022
  6097                              <1> 	;mov	[HF_ERROR], al
  6098                              <1> 	;push	ebx	; 21/02/2015
  6099 00002474 29C9                <1> 	sub	ecx, ecx
  6100                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  6101 00002476 B108                <1> 	mov	cl, 8
  6102                              <1> CK1:	
  6103 00002478 D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  6104 0000247A 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  6105 0000247C E2FA                <1> 	loop	CK1			; KEEP TRYING
  6106                              <1> CK2:
  6107                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  6108                              <1> 	;add	ebx, ecx		; ERROR CODE
  6109 0000247E 81C1[38630000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  6110                              <1> 
  6111                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  6112                              <1> 	;;mov	ah, [bx]
  6113                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  6114 00002484 8A21                <1> 	mov	ah, [ecx]	
  6115                              <1> CKEX:
  6116 00002486 8825[BB680000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  6117                              <1> 	; 10/07/2022
  6118                              <1> 	;pop	ebx
  6119                              <1> 	;;cmp	ah, 0
  6120                              <1> 	;and	ah, ah
  6121 0000248C C3                  <1> 	retn
  6122                              <1> 
  6123                              <1> ;--------------------------------------------------------
  6124                              <1> ; CHECK_DMA						:
  6125                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  6126                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  6127                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  6128                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  6129                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  6130                              <1> ;  -ERROR OTHERWISE					:
  6131                              <1> ;--------------------------------------------------------
  6132                              <1> 
  6133                              <1> 	; 11/07/2022
  6134                              <1> 	; (not needed for hard disks and 32 bit OS)
  6135                              <1> 	;
  6136                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6137                              <1> ;CHECK_DMA:
  6138                              <1> ;	;;push	ax			; SAVE REGISTERS
  6139                              <1> ;	;; 24/12/2021
  6140                              <1> ;	;;push	eax
  6141                              <1> ;	;mov	ax, 8000h		; AH = MAX # SECTORS
  6142                              <1> ;					; AL = MAX OFFSET
  6143                              <1> ;	; 10/07/2022
  6144                              <1> ;	;test	byte [CMD_BLOCK+6], ECC_MODE
  6145                              <1> ;	;jz	short CKD1
  6146                              <1> ;	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  6147                              <1> ;CKD1:	
  6148                              <1> ;	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  6149                              <1> ;	;ja	short CKDOK		; IT WILL FIT
  6150                              <1> ;	;jb	short CKDERR		; TOO MANY
  6151                              <1> ;	
  6152                              <1> ;	cmp	byte [CMD_BLOCK+1], 80h
  6153                              <1> ;	jb	short CKDOK
  6154                              <1> ;	ja	short CKDERR
  6155                              <1> ;	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  6156                              <1> ;	;jb	short CKDERR		; ERROR
  6157                              <1> ;CKD2:
  6158                              <1> ;	or	bl, bl
  6159                              <1> ;	jz	short CKDR
  6160                              <1> ;	
  6161                              <1> ;;CKDOK:	
  6162                              <1> ;	;clc				; CLEAR CARRY
  6163                              <1> ;	;;pop	ax
  6164                              <1> ;	;; 24/12/2021
  6165                              <1> ;	;pop	eax
  6166                              <1> ;	;retn				; NORMAL RETURN
  6167                              <1> ;CKDERR: 
  6168                              <1> ;	stc				; INDICATE ERROR
  6169                              <1> ;	mov	byte [DISK_STATUS1], DMA_BOUNDARY
  6170                              <1> ;	;;pop	ax
  6171                              <1> ;	;; 24/12/2021
  6172                              <1> ;	;pop	eax	
  6173                              <1> ;	retn
  6174                              <1> ;
  6175                              <1> ;	; 10/07/2022
  6176                              <1> ;CKDOK:
  6177                              <1> ;	clc
  6178                              <1> ;CKDR:
  6179                              <1> ;	retn
  6180                              <1> 
  6181                              <1> ;----------------------------------------
  6182                              <1> ;	SET UP EBX-> DISK PARMS	        :
  6183                              <1> ;----------------------------------------
  6184                              <1> 					
  6185                              <1> ; INPUT -> DL = 0 based drive number
  6186                              <1> ; OUTPUT -> EBX = disk parameter table address
  6187                              <1> 
  6188                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6189                              <1> 
  6190                              <1> GET_VEC:
  6191                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  6192                              <1> 	;mov	es, ax
  6193                              <1> 	;test	dl, 1
  6194                              <1> 	;jz	short GV_0
  6195                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  6196                              <1> ;	jmp	short GV_EXIT
  6197                              <1> ;GV_0:
  6198                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  6199                              <1> ;
  6200 0000248D 31DB                <1> 	xor	ebx, ebx
  6201 0000248F 88D3                <1> 	mov	bl, dl
  6202                              <1> 	;02/01/2015
  6203                              <1> 	;xor	bh, bh
  6204                              <1> 	;shl	bl, 1			; port address offset
  6205                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  6206                              <1> 	;shl	bl, 1			; dpt pointer offset
  6207 00002491 C0E302              <1> 	shl	bl, 2
  6208                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  6209 00002494 81C3[C0680000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  6210                              <1> 	;push	word [bx+2]		; dpt segment
  6211                              <1> 	;pop	es
  6212                              <1> 	;mov	bx, [bx]		; dpt offset
  6213 0000249A 8B1B                <1> 	mov	ebx, [ebx]		
  6214                              <1> ;GV_EXIT:
  6215 0000249C C3                  <1> 	retn
  6216                              <1> 
  6217                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6218                              <1> hdc1_int: ; 21/02/2015
  6219                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  6220                              <1> ;								:
  6221                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6222                              <1> ;								:
  6223                              <1> ;----------------------------------------------------------------
  6224                              <1> 
  6225                              <1> ; 22/12/2014
  6226                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  6227                              <1> ;	 '11/15/85'
  6228                              <1> ; AWARD BIOS 1999 (D1A0622) 
  6229                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  6230                              <1> 
  6231                              <1> ;int_76h:
  6232                              <1> HD_INT:
  6233                              <1> 	;push	ax
  6234                              <1> 	; 24/12/2021
  6235 0000249D 50                  <1> 	push	eax
  6236 0000249E 1E                  <1> 	push	ds
  6237                              <1> 	;CALL	DDS
  6238                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6239 0000249F 66B81000            <1> 	mov	ax, KDATA
  6240 000024A3 8ED8                <1> 	mov 	ds, ax
  6241                              <1> 	;
  6242                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  6243                              <1>         ;mov	byte [CS:HF_INT_FLAG], 0FFh
  6244 000024A5 C605[B6680000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  6245                              <1> 	;
  6246                              <1> 	;push	dx
  6247                              <1> 	; 24/12/2021
  6248 000024AC 52                  <1> 	push	edx
  6249 000024AD 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  6250                              <1> 					; Clear Controller
  6251                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  6252 000024B1 EC                  <1> 	in	al, dx			;
  6253                              <1> 	;pop	dx
  6254                              <1> 	; 24/12/2021
  6255 000024B2 5A                  <1> 	pop	edx
  6256                              <1> 	NEWIODELAY
  2175 000024B3 E6EB                <2>  out 0EBh,al
  6257                              <1> 	;
  6258 000024B5 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  6259 000024B7 E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  6260                              <1> 	;JMP	$+2			; WAIT
  6261                              <1> 	NEWIODELAY
  2175 000024B9 E6EB                <2>  out 0EBh,al
  6262 000024BB E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  6263 000024BD 1F                  <1> 	pop	ds
  6264                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  6265                              <1> 	;mov	ax, 9100h		; DEVICE POST
  6266                              <1> 	;int	15h			; INTERRUPT
  6267                              <1> irq15_iret: ; 25/02/2015
  6268                              <1> 	;pop	ax
  6269                              <1> 	; 24/12/2021
  6270 000024BE 58                  <1> 	pop	eax
  6271 000024BF CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  6272                              <1> 
  6273                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6274                              <1> hdc2_int: ; 21/02/2015
  6275                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  6276                              <1> ;								:
  6277                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6278                              <1> ;								:
  6279                              <1> ;----------------------------------------------------------------
  6280                              <1> 
  6281                              <1> ;int_77h:
  6282                              <1> HD1_INT:
  6283                              <1> 	;push	ax
  6284                              <1> 	; 24/12/2021
  6285 000024C0 50                  <1> 	push	eax
  6286                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  6287                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  6288 000024C1 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  6289 000024C3 E6A0                <1> 	out	0A0h, al
  6290 000024C5 EB00                <1>         jmp short $+2
  6291 000024C7 EB00                <1> 	jmp short $+2
  6292 000024C9 E4A0                <1> 	in	al, 0A0h
  6293 000024CB 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  6294 000024CD 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  6295                              <1> 	;
  6296 000024CF 1E                  <1> 	push	ds
  6297                              <1> 	;CALL	DDS
  6298                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6299 000024D0 66B81000            <1> 	mov	ax, KDATA
  6300 000024D4 8ED8                <1> 	mov 	ds, ax
  6301                              <1> 	;
  6302                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  6303                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  6304 000024D6 800D[B6680000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  6305                              <1> 	;
  6306                              <1> 	;push	dx
  6307                              <1> 	; 24/12/2021
  6308 000024DD 52                  <1> 	push	edx
  6309 000024DE 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6310                              <1> 					; Clear Controller (Award BIOS 1999)
  6311 000024E2 EBCD                <1> 	jmp	short Clear_IRQ1415
  6312                              <1> 
  6313                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6314                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6315                              <1> 
  6316                              <1> ;////////////////////////////////////////////////////////////////////
  6317                              <1> ;; END OF DISK I/O SYTEM ///
  2084                                  %include 'memory.s'  ; 09/03/2015
  2085                              <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020
  2086                              <1> ; Last Modification: 31/12/2021 (Retro UNIX 386 v1.2)
  2087                              <1> ; ----------------------------------------------------------------------------
  2088                              <1> ;
  2089                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2090                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC
  2091                              <1> ; 18/10/2015 (!not completed!)
  2092                              <1> ;
  2093                              <1> ; Source code for NASM - Netwide Assembler (2.11)
  2094                              <1> 
  2095                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2096                              <1> 
  2097                              <1> ;;04/11/2014 (unix386.s)	
  2098                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2099                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2100                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2101                              <1> ;;
  2102                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2103                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2104                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2105                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2106                              <1> 
  2107                              <1> ; 27/04/2015
  2108                              <1> ; 09/03/2015
  2109                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2110                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2111                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2112                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2113                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2114                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2115                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2116                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2117                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2118                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2119                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2120                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2121                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2122                              <1> SWP_DISK_READ_ERR 	   equ 40
  2123                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2124                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2125                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2126                              <1> SWP_DISK_WRITE_ERR         equ 44
  2127                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2128                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2129                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2130                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2131                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2132                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2133                              <1> 					; (Indicates that the page is not allocated
  2134                              <1> 					; for the process, it is a shared or system
  2135                              <1>                                         ; page, it must not be deallocated!)
  2136                              <1> ; 14/12/2020
  2137                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2138                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2139                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2140                              <1> 				; (Out of memory allocation table)	
  2141                              <1> ;
  2142                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2143                              <1> ;;
  2144                              <1> ;; 10/10/2014
  2145                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2146                              <1> ;;
  2147                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2148                              <1> ;;	(virtual address = physical address)
  2149                              <1> ;; KERNEL PAGE TABLES:
  2150                              <1> ;;	Kernel page directory and all page tables are
  2151                              <1> ;;	on memory as initialized, as equal to physical memory
  2152                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2153                              <1> ;;
  2154                              <1> ;;	what for: User pages may be swapped out, when accessing
  2155                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2156                              <1> ;;	kernel would have to swap it in! But it is also may be
  2157                              <1> ;;	in use by a user process. (In system/kernel mode
  2158                              <1> ;;	kernel can access all memory pages even if they are
  2159                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2160                              <1> ;;	cause conflicts.) 
  2161                              <1> ;;	
  2162                              <1> ;;	As result of these conditions,
  2163                              <1> ;;	all kernel pages must be initialized as equal to 
  2164                              <1> ;;	physical layout for preventing page faults. 
  2165                              <1> ;;	Also, calling "allocate page" procedure after
  2166                              <1> ;;	a page fault can cause another page fault (double fault)
  2167                              <1> ;;	if all kernel page tables would not be initialized.
  2168                              <1> ;;
  2169                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2170                              <1> ;;	memory allocation table. (double word aligned)
  2171                              <1> ;;
  2172                              <1> ;;	[next_page] = first/next free space to be searched
  2173                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2174                              <1> ;;
  2175                              <1> ;;	[last_page] = End of memory (users space), as offset
  2176                              <1> ;;	to memory allocation table. (double word aligned)
  2177                              <1> ;;
  2178                              <1> ;; USER PAGE TABLES:
  2179                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2180                              <1> ;;		'ready only' marked copies of the 
  2181                              <1> ;;		parent process's page table entries (for
  2182                              <1> ;;		same physical memory).
  2183                              <1> ;;		(A page will be copied to a new page after
  2184                              <1> ;;		 if it causes R/W page fault.)
  2185                              <1> ;;
  2186                              <1> ;;	Every user process has own (different)
  2187                              <1> ;;	page directory and page tables.	
  2188                              <1> ;;
  2189                              <1> ;;	Code starts at virtual address 0, always.
  2190                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2191                              <1> ;;	(Programs can be written/developed as simple
  2192                              <1> ;;	 flat memory programs.)
  2193                              <1> ;;
  2194                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2195                              <1> ;;	Memory page will be allocated by kernel only 
  2196                              <1> ;;		(in kernel/system mode only).
  2197                              <1> ;;	* After a
  2198                              <1> ;;	  - 'not present' page fault
  2199                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2200                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2201                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2202                              <1> ;;	  request by running process.
  2203                              <1> ;;	* While creating a process, allocating a new buffer,
  2204                              <1> ;;	  new page tables etc.
  2205                              <1> ;;
  2206                              <1> ;;	At first,
  2207                              <1> ;;	- 'allocate page' procedure will be called;
  2208                              <1> ;,	   if it will return with a valid (>0) physical address
  2209                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2210                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2211                              <1> ;;	- 'allocate page' will be called for allocating page
  2212                              <1> ;;	   directory, page table and running space (data/code).
  2213                              <1> ;;	- every successful 'allocate page' call will decrease
  2214                              <1> ;;	  'free_pages' count (pointer).
  2215                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2216                              <1> ;;	  if 'free_pages' points to a ZERO.
  2217                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2218                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2219                              <1> ;;	  error except errors caused by attribute conflicts.
  2220                              <1> ;;	 (swapper functions)	 
  2221                              <1> ;;					
  2222                              <1> ;;	At second,
  2223                              <1> ;;	- page directory entry will be updated then page table
  2224                              <1> ;;	  entry will be updated.		
  2225                              <1> ;;
  2226                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2227                              <1> ;;	- M.A.T. has a size according to available memory as
  2228                              <1> ;;	  follows:
  2229                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2230                              <1> ;;		  - a bit with value of 0 means allocated page
  2231                              <1> ;;		  - a bit with value of 1 means a free page
  2232                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2233                              <1> ;;	  depending on M.A.T.
  2234                              <1> ;;		(NOTE: Free page count will not be checked
  2235                              <1> ;;		again -on M.A.T.- after initialization. 
  2236                              <1> ;;		Kernel will trust on initial count.)
  2237                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2238                              <1> ;;	  and it will be increased by deallocation procedures.
  2239                              <1> ;;	
  2240                              <1> ;;	- Available memory will be calculated during
  2241                              <1> ;;	  the kernel's initialization stage (in real mode).
  2242                              <1> ;;	  Memory allocation table and kernel page tables 
  2243                              <1> ;;	  will be formatted/sized as result of available
  2244                              <1> ;;	  memory calculation before paging is enabled.
  2245                              <1> ;;
  2246                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2247                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2248                              <1> ;;	- Memory allocation for kernel page directory size 
  2249                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2250                              <1> ;;	  for page tables)
  2251                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2252                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2253                              <1> ;;	- User (available) space will be started 
  2254                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2255                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2256                              <1> ;;	  memory allocation table and kernel's page directory
  2257                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2258                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2259                              <1> ;; 	  for buffers.
  2260                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2261                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2262                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2263                              <1> ;;
  2264                              <1> ;; For 1GB Available Memory:
  2265                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2266                              <1> ;;	- Memory allocation for kernel page directory size 
  2267                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2268                              <1> ;;	  for page tables)
  2269                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2270                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2271                              <1> ;;	- User (available) space will be started 
  2272                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2273                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2274                              <1> ;;	  memory allocation table and kernel's page directory
  2275                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2276                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2277                              <1> ;; 	  for buffers.
  2278                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2279                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2280                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2281                              <1> ;;
  2282                              <1> ;;
  2283                              <1> 
  2284                              <1> ;;************************************************************************************
  2285                              <1> ;; 
  2286                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2287                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2288                              <1> 
  2289                              <1> ;; Main factor: "sys fork" system call 
  2290                              <1> ;;	
  2291                              <1> ;; 		FORK
  2292                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2293                              <1> ;;  writable pages ---->|
  2294                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2295                              <1> ;; 
  2296                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2297                              <1> ;; 
  2298                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2299                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2300                              <1> ;;       -while R/W bit is 0-. 
  2301                              <1> ;; 
  2302                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2303                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2304                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2305                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2306                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2307                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2308                              <1> ;; 
  2309                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2310                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2311                              <1> ;;   Parent's PTE attributes are not changed.
  2312                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2313                              <1> ;;    destroy/mix previous fork result).
  2314                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2315                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2316                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2317                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2318                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2319                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2320                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2321                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2322                              <1> ;; 
  2323                              <1> ;; !? WHAT FOR (duplication after duplication):
  2324                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2325                              <1> ;; program/executable code continues from specified location as child process, 
  2326                              <1> ;; returns back previous code location as parent process, every child after 
  2327                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2328                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2329                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2330                              <1> ;; was copied to child's process segment (all of code and data) according to
  2331                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2332                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2333                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2334                              <1> ;; (complete running image of parent process) to the child process; 
  2335                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2336                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2337                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2338                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2339                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2340                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2341                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2342                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2343                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2344                              <1> ;; for sharing same read only pages between parent and child processes.
  2345                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2346                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2347                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2348                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2349                              <1> ;; -deallocation problem-.
  2350                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2351                              <1> ;; 
  2352                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2353                              <1> ;; # Page fault handler will do those:
  2354                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2355                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2356                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2357                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2358                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2359                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2360                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2361                              <1> ;;     to child process.)	
  2362                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2363                              <1> ;; # Page fault handler will do those:
  2364                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2365                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2366                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2367                              <1> ;;     address or not. 
  2368                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2369                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2370                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2371                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2372                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2373                              <1> ;; 
  2374                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2375                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2376                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2377                              <1> ;;       duplication method details, it is not possible multiple child processes
  2378                              <1> ;;       were using same page with duplicated PTEs.
  2379                              <1> ;; 
  2380                              <1> ;;************************************************************************************   
  2381                              <1> 
  2382                              <1> ;; 08/10/2014
  2383                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2384                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2385                              <1> 
  2386                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2387                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2388                              <1> ;; (25/08/2014, Revision: 5057) file 
  2389                              <1> ;; by KolibriOS Team (2004-2012)
  2390                              <1> 
  2391                              <1> allocate_page:
  2392                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2393                              <1> 	;	 (temporary modifications)
  2394                              <1> 	; 01/07/2015
  2395                              <1> 	; 05/05/2015
  2396                              <1> 	; 30/04/2015
  2397                              <1> 	; 16/10/2014
  2398                              <1> 	; 08/10/2014
  2399                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2400                              <1> 	;
  2401                              <1> 	; INPUT -> none
  2402                              <1> 	;
  2403                              <1> 	; OUTPUT ->
  2404                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2405                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2406                              <1> 	;
  2407                              <1> 	;	CF = 1 and EAX = 0 
  2408                              <1> 	; 		   if there is not a free page to be allocated	
  2409                              <1> 	;
  2410                              <1> 	; Modified Registers -> none (except EAX)
  2411                              <1> 	;
  2412 000024E4 A1[30680000]        <1> 	mov	eax, [free_pages]
  2413 000024E9 21C0                <1> 	and	eax, eax
  2414 000024EB 7438                <1> 	jz	short out_of_memory
  2415                              <1> 	;
  2416 000024ED 53                  <1> 	push	ebx
  2417 000024EE 51                  <1> 	push	ecx
  2418                              <1> 	;
  2419 000024EF BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2420 000024F4 89D9                <1> 	mov	ecx, ebx
  2421                              <1>  				     ; NOTE: 32 (first_page) is initial
  2422                              <1> 				     ; value of [next_page].
  2423                              <1> 				     ; It points to the first available
  2424                              <1> 				     ; page block for users (ring 3) ...	
  2425                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2426                              <1> 				     ; (at the of the first 4 MB)		
  2427 000024F6 031D[34680000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2428                              <1> 				 ; next_free_page >> 5
  2429 000024FC 030D[38680000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2430                              <1> 				 ; (total_pages - 1) >> 5
  2431                              <1> al_p_scan:
  2432 00002502 39CB                <1> 	cmp	ebx, ecx
  2433 00002504 770A                <1> 	ja	short al_p_notfound
  2434                              <1> 	;
  2435                              <1> 	; 01/07/2015
  2436                              <1> 	; AMD64 Architecture Programmers Manual
  2437                              <1> 	; Volume 3:
  2438                              <1> 	; General-Purpose and System Instructions
  2439                              <1> 	;
  2440                              <1> 	; BSF - Bit Scan Forward
  2441                              <1> 	;
  2442                              <1> 	;   Searches the value in a register or a memory location
  2443                              <1> 	;   (second operand) for the least-significant set bit. 
  2444                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2445                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2446                              <1> 	;   register (first operand). If the second operand contains 0, 
  2447                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2448                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2449                              <1> 	;   of the searched value
  2450                              <1> 	;
  2451 00002506 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2452                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2453                              <1> 			   ; loads the destination with an index to
  2454                              <1> 			   ; first set bit. (0 -> 31) 
  2455                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2456 00002509 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2457                              <1> 			 ;
  2458                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2459                              <1> 			 ;	  with value of 1 means 
  2460                              <1> 			 ;	  the corresponding page is free 
  2461                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2462 0000250B 83C304              <1> 	add	ebx, 4
  2463                              <1> 			 ; We return back for searching next page block
  2464                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2465                              <1> 			 ;	 we always will find at least 1 free page here.
  2466 0000250E EBF2                <1>         jmp     short al_p_scan
  2467                              <1> 	;
  2468                              <1> al_p_notfound:
  2469 00002510 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2470 00002516 890D[34680000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2471                              <1> 				 ; (deallocate_page procedure will change it)
  2472 0000251C 31C0                <1> 	xor	eax, eax
  2473 0000251E A3[30680000]        <1> 	mov	[free_pages], eax ; 0
  2474 00002523 59                  <1> 	pop	ecx
  2475 00002524 5B                  <1> 	pop	ebx
  2476                              <1> 	;
  2477                              <1> ; 17/04/2021
  2478                              <1> ; ('swap_out' procedure call is disabled as temporary)
  2479                              <1> 
  2480                              <1> out_of_memory:
  2481                              <1> ;	call	swap_out
  2482                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2483                              <1> ;	;
  2484                              <1> ;	sub 	eax, eax ; 0
  2485 00002525 F9                  <1> 	stc
  2486 00002526 C3                  <1> 	retn
  2487                              <1> 
  2488                              <1> al_p_found:
  2489 00002527 89D9                <1> 	mov	ecx, ebx
  2490 00002529 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2491 0000252F 890D[34680000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2492                              <1> 				 ; address/offset (to the next)
  2493 00002535 FF0D[30680000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2494                              <1> 	;
  2495 0000253B 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2496                              <1> 				 ; is copied into the Carry Flag and then cleared
  2497                              <1> 				 ; in the destination.
  2498                              <1> 				 ;
  2499                              <1> 				 ; Reset the bit which is corresponding to the 
  2500                              <1> 				 ; (just) allocated page.
  2501                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2502 0000253E C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2503 00002541 01C8                <1> 	add	eax, ecx	 ; = page number
  2504 00002543 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2505                              <1> 	; EAX = physical address of memory page
  2506                              <1> 	;
  2507                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2508                              <1> 	;       according to this EAX value...
  2509 00002546 59                  <1> 	pop	ecx
  2510 00002547 5B                  <1> 	pop	ebx
  2511                              <1> al_p_ok:
  2512 00002548 C3                  <1> 	retn
  2513                              <1> 
  2514                              <1> make_page_dir:
  2515                              <1> 	; 18/04/2015
  2516                              <1> 	; 12/04/2015
  2517                              <1> 	; 23/10/2014
  2518                              <1> 	; 16/10/2014
  2519                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2520                              <1> 	;
  2521                              <1> 	; INPUT ->
  2522                              <1> 	;	none
  2523                              <1> 	; OUTPUT ->
  2524                              <1> 	;	(EAX = 0)
  2525                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2526                              <1> 	;	cf = 0 ->
  2527                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2528                              <1> 	;		  process/user.
  2529                              <1> 	;
  2530                              <1> 	; Modified Registers -> EAX
  2531                              <1> 	;
  2532 00002549 E896FFFFFF          <1> 	call	allocate_page
  2533 0000254E 7216                <1> 	jc	short mkpd_error
  2534                              <1> 	;
  2535 00002550 A3[C46D0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2536                              <1> 				  ; (Physical address)
  2537                              <1> clear_page:
  2538                              <1> 	; 18/04/2015
  2539                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2540                              <1> 	;
  2541                              <1> 	; INPUT ->
  2542                              <1> 	;	EAX = physical address of the page
  2543                              <1> 	; OUTPUT ->
  2544                              <1> 	;	all bytes of the page will be cleared
  2545                              <1> 	;
  2546                              <1> 	; Modified Registers -> none
  2547                              <1> 	;
  2548 00002555 57                  <1> 	push	edi
  2549 00002556 51                  <1> 	push	ecx
  2550 00002557 50                  <1> 	push	eax
  2551 00002558 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2552 0000255D 89C7                <1> 	mov	edi, eax
  2553 0000255F 31C0                <1> 	xor	eax, eax
  2554 00002561 F3AB                <1> 	rep	stosd
  2555 00002563 58                  <1> 	pop	eax
  2556 00002564 59                  <1> 	pop	ecx
  2557 00002565 5F                  <1> 	pop	edi
  2558                              <1> mkpd_error:
  2559                              <1> mkpt_error:
  2560 00002566 C3                  <1> 	retn
  2561                              <1> 
  2562                              <1> make_page_table:
  2563                              <1> 	; 23/06/2015
  2564                              <1> 	; 18/04/2015
  2565                              <1> 	; 12/04/2015
  2566                              <1> 	; 16/10/2014
  2567                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2568                              <1> 	;
  2569                              <1> 	; INPUT ->
  2570                              <1> 	;	EBX = virtual (linear) address
  2571                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2572                              <1> 	;	      (higher 20 bits must be ZERO)
  2573                              <1> 	;	      (bit 0 must be 1)	 
  2574                              <1> 	;	u.pgdir = page directory (physical) address
  2575                              <1> 	; OUTPUT ->
  2576                              <1> 	;	EDX = Page directory entry address
  2577                              <1> 	;	EAX = Page table address
  2578                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2579                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2580                              <1> 	;
  2581                              <1> 	; Modified Registers -> EAX, EDX
  2582                              <1> 	;
  2583 00002567 E878FFFFFF          <1> 	call	allocate_page
  2584 0000256C 72F8                <1> 	jc	short mkpt_error
  2585 0000256E E811000000          <1> 	call	set_pde	
  2586 00002573 EBE0                <1> 	jmp	short clear_page
  2587                              <1> 
  2588                              <1> make_page:
  2589                              <1> 	; 24/07/2015
  2590                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2591                              <1> 	;
  2592                              <1> 	; INPUT ->
  2593                              <1> 	;	EBX = virtual (linear) address
  2594                              <1> 	;	ECX = page attributes (lower 12 bits)
  2595                              <1> 	;	      (higher 20 bits must be ZERO)
  2596                              <1> 	;	      (bit 0 must be 1)	 
  2597                              <1> 	;	u.pgdir = page directory (physical) address
  2598                              <1> 	; OUTPUT ->
  2599                              <1> 	;	EBX = Virtual address
  2600                              <1> 	;	(EDX = PTE value)
  2601                              <1> 	;	EAX = Physical address
  2602                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2603                              <1> 	;
  2604                              <1> 	; Modified Registers -> EAX, EDX
  2605                              <1> 	;
  2606 00002575 E86AFFFFFF          <1> 	call	allocate_page
  2607 0000257A 7207                <1> 	jc	short mkp_err
  2608 0000257C E821000000          <1> 	call	set_pte	
  2609 00002581 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2610                              <1> mkp_err:
  2611 00002583 C3                  <1> 	retn
  2612                              <1> 
  2613                              <1> set_pde:	; Set page directory entry (PDE)
  2614                              <1> 	; 20/07/2015
  2615                              <1> 	; 18/04/2015
  2616                              <1> 	; 12/04/2015
  2617                              <1> 	; 23/10/2014
  2618                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2619                              <1> 	;
  2620                              <1> 	; INPUT ->
  2621                              <1> 	;	EAX = physical address
  2622                              <1> 	;	      (use present value if EAX = 0)
  2623                              <1> 	;	EBX = virtual (linear) address
  2624                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2625                              <1> 	;	      (higher 20 bits must be ZERO)
  2626                              <1> 	;	      (bit 0 must be 1)	 
  2627                              <1> 	;	u.pgdir = page directory (physical) address
  2628                              <1> 	; OUTPUT ->
  2629                              <1> 	;	EDX = PDE address
  2630                              <1> 	;	EAX = page table address (physical)
  2631                              <1> 	;	;(CF=1 -> Invalid page address)
  2632                              <1> 	;
  2633                              <1> 	; Modified Registers -> EDX
  2634                              <1> 	;
  2635 00002584 89DA                <1> 	mov	edx, ebx
  2636 00002586 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2637 00002589 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2638 0000258C 0315[C46D0000]      <1> 	add	edx, [u.pgdir]
  2639                              <1> 	;
  2640 00002592 21C0                <1> 	and	eax, eax
  2641 00002594 7506                <1> 	jnz	short spde_1
  2642                              <1> 	;
  2643 00002596 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2644                              <1> 	;test	al, 1
  2645                              <1> 	;jz	short spde_2
  2646 00002598 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2647                              <1> spde_1:
  2648                              <1> 	;and	cx, 0FFFh
  2649 0000259C 8902                <1> 	mov	[edx], eax
  2650 0000259E 66090A              <1> 	or	[edx], cx
  2651 000025A1 C3                  <1> 	retn
  2652                              <1> ;spde_2: ; error
  2653                              <1> ;	stc
  2654                              <1> ;	retn
  2655                              <1> 
  2656                              <1> set_pte:	; Set page table entry (PTE)
  2657                              <1> 	; 24/07/2015
  2658                              <1> 	; 20/07/2015
  2659                              <1> 	; 23/06/2015
  2660                              <1> 	; 18/04/2015
  2661                              <1> 	; 12/04/2015
  2662                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2663                              <1> 	;
  2664                              <1> 	; INPUT ->
  2665                              <1> 	;	EAX = physical page address
  2666                              <1> 	;	      (use present value if EAX = 0)
  2667                              <1> 	;	EBX = virtual (linear) address
  2668                              <1> 	;	ECX = page attributes (lower 12 bits)
  2669                              <1> 	;	      (higher 20 bits must be ZERO)
  2670                              <1> 	;	      (bit 0 must be 1)	 
  2671                              <1> 	;	u.pgdir = page directory (physical) address
  2672                              <1> 	; OUTPUT ->
  2673                              <1> 	;	EAX = physical page address
  2674                              <1> 	;	(EDX = PTE value)
  2675                              <1> 	;	EBX = virtual address
  2676                              <1> 	;
  2677                              <1> 	;	CF = 1 -> error
  2678                              <1> 	;
  2679                              <1> 	; Modified Registers -> EAX, EDX
  2680                              <1> 	;
  2681 000025A2 50                  <1> 	push	eax
  2682 000025A3 A1[C46D0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2683 000025A8 E837000000          <1> 	call 	get_pde
  2684                              <1> 		; EDX = PDE address
  2685                              <1> 		; EAX = PDE value
  2686 000025AD 5A                  <1> 	pop	edx ; physical page address
  2687 000025AE 722A                <1> 	jc	short spte_err ; PDE not present
  2688                              <1> 	;
  2689 000025B0 53                  <1> 	push	ebx ; 24/07/2015
  2690 000025B1 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2691                              <1> 			    ; EDX = PT address (physical)	
  2692 000025B5 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2693 000025B8 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2694                              <1> 			 ; clear higher 10 bits (PD bits)
  2695 000025BE C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2696 000025C1 01C3                <1> 	add	ebx, eax
  2697                              <1> 	;
  2698 000025C3 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2699 000025C5 A801                <1> 	test	al, 1
  2700 000025C7 740C                <1> 	jz	short spte_0
  2701 000025C9 09D2                <1> 	or	edx, edx
  2702 000025CB 750F                <1> 	jnz	short spte_1
  2703 000025CD 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2704 000025D1 89C2                <1> 	mov	edx, eax
  2705 000025D3 EB09                <1> 	jmp	short spte_2	
  2706                              <1> spte_0:
  2707                              <1> 	; If this PTE contains a swap (disk) address,
  2708                              <1> 	; it can be updated by using 'swap_in' procedure
  2709                              <1> 	; only!
  2710 000025D5 21C0                <1> 	and	eax, eax
  2711 000025D7 7403                <1> 	jz	short spte_1
  2712                              <1> 	; 24/07/2015
  2713                              <1> 	; swapped page ! (on disk)
  2714 000025D9 5B                  <1> 	pop	ebx
  2715                              <1> spte_err:
  2716 000025DA F9                  <1> 	stc
  2717 000025DB C3                  <1> 	retn
  2718                              <1> spte_1: 
  2719 000025DC 89D0                <1> 	mov	eax, edx
  2720                              <1> spte_2:
  2721 000025DE 09CA                <1> 	or	edx, ecx
  2722                              <1> 	; 23/06/2015
  2723 000025E0 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2724                              <1> 	; 24/07/2015
  2725 000025E2 5B                  <1> 	pop	ebx
  2726 000025E3 C3                  <1> 	retn
  2727                              <1> 
  2728                              <1> get_pde:	; Get present value of the relevant PDE
  2729                              <1> 	; 20/07/2015
  2730                              <1> 	; 18/04/2015
  2731                              <1> 	; 12/04/2015
  2732                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2733                              <1> 	;
  2734                              <1> 	; INPUT ->
  2735                              <1> 	;	EBX = virtual (linear) address
  2736                              <1> 	;	EAX = page directory (physical) address
  2737                              <1> 	; OUTPUT ->
  2738                              <1> 	;	EDX = Page directory entry address
  2739                              <1> 	;	EAX = Page directory entry value
  2740                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2741                              <1> 	; Modified Registers -> EDX, EAX
  2742                              <1> 	;
  2743 000025E4 89DA                <1> 	mov	edx, ebx
  2744 000025E6 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2745 000025E9 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2746 000025EC 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2747 000025EE 8B02                <1> 	mov	eax, [edx]
  2748 000025F0 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2749 000025F2 751F                <1> 	jnz	short gpte_retn
  2750 000025F4 F9                  <1> 	stc
  2751                              <1> gpde_retn:	
  2752 000025F5 C3                  <1> 	retn
  2753                              <1> 
  2754                              <1> get_pte:
  2755                              <1> 		; Get present value of the relevant PTE
  2756                              <1> 	; 29/07/2015
  2757                              <1> 	; 20/07/2015
  2758                              <1> 	; 18/04/2015
  2759                              <1> 	; 12/04/2015
  2760                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2761                              <1> 	;
  2762                              <1> 	; INPUT ->
  2763                              <1> 	;	EBX = virtual (linear) address
  2764                              <1> 	;	EAX = page directory (physical) address
  2765                              <1> 	; OUTPUT ->
  2766                              <1> 	;	EDX = Page table entry address (if CF=0)
  2767                              <1> 	;	      Page directory entry address (if CF=1)
  2768                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2769                              <1> 	;	EAX = Page table entry value (page address)
  2770                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2771                              <1> 	; Modified Registers -> EAX, EDX
  2772                              <1> 	;
  2773 000025F6 E8E9FFFFFF          <1> 	call 	get_pde
  2774 000025FB 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2775                              <1> 	;jnc	short gpte_1
  2776                              <1> 	;retn
  2777                              <1> ;gpte_1:
  2778 000025FD 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2779 00002601 89DA                <1> 	mov	edx, ebx
  2780 00002603 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2781 00002606 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2782                              <1> 			 ; clear higher 10 bits (PD bits)
  2783 0000260C C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2784 0000260F 01C2                <1> 	add	edx, eax
  2785 00002611 8B02                <1> 	mov	eax, [edx]
  2786                              <1> gpte_retn:
  2787 00002613 C3                  <1> 	retn
  2788                              <1> 
  2789                              <1> deallocate_page_dir:
  2790                              <1> 	; 15/09/2015
  2791                              <1> 	; 05/08/2015
  2792                              <1> 	; 30/04/2015
  2793                              <1> 	; 28/04/2015
  2794                              <1> 	; 17/10/2014
  2795                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2796                              <1> 	;
  2797                              <1> 	; INPUT ->
  2798                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2799                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2800                              <1> 	; OUTPUT ->
  2801                              <1> 	;	All of page tables in the page directory
  2802                              <1> 	;	and page dir's itself will be deallocated
  2803                              <1> 	;	except 'read only' duplicated pages (will be converted
  2804                              <1> 	;	to writable pages).
  2805                              <1> 	;
  2806                              <1> 	; Modified Registers -> EAX
  2807                              <1> 	;
  2808                              <1> 	;
  2809 00002614 56                  <1> 	push	esi
  2810 00002615 51                  <1> 	push	ecx
  2811 00002616 50                  <1> 	push	eax
  2812 00002617 89C6                <1> 	mov	esi, eax 
  2813 00002619 31C9                <1> 	xor	ecx, ecx
  2814                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2815                              <1> 	; it must not be deallocated
  2816 0000261B 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2817                              <1> dapd_0:
  2818 0000261D AD                  <1> 	lodsd
  2819 0000261E A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2820 00002620 7409                <1> 	jz	short dapd_1	
  2821 00002622 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2822 00002626 E812000000          <1> 	call	deallocate_page_table			
  2823                              <1> dapd_1:
  2824 0000262B 41                  <1> 	inc	ecx ; page directory entry index
  2825 0000262C 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2826 00002632 72E9                <1> 	jb	short dapd_0
  2827                              <1> dapd_2:
  2828 00002634 58                  <1> 	pop	eax
  2829 00002635 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2830 0000263A 59                  <1> 	pop	ecx
  2831 0000263B 5E                  <1> 	pop	esi
  2832 0000263C C3                  <1> 	retn
  2833                              <1> 
  2834                              <1> deallocate_page_table:
  2835                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2836                              <1> 	;	 (temporary modifications)
  2837                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2838                              <1> 	; 19/09/2015
  2839                              <1> 	; 15/09/2015
  2840                              <1> 	; 05/08/2015
  2841                              <1> 	; 30/04/2015
  2842                              <1> 	; 28/04/2015
  2843                              <1> 	; 24/10/2014
  2844                              <1> 	; 23/10/2014
  2845                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2846                              <1> 	;
  2847                              <1> 	; INPUT ->
  2848                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2849                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2850                              <1> 	;	(ECX = page directory entry index)
  2851                              <1> 	; OUTPUT ->
  2852                              <1> 	;	All of pages in the page table and page table's itself
  2853                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2854                              <1> 	;	(will be converted to writable pages).
  2855                              <1> 	;
  2856                              <1> 	; Modified Registers -> EAX
  2857                              <1> 	;
  2858 0000263D 56                  <1> 	push	esi
  2859 0000263E 57                  <1> 	push	edi
  2860 0000263F 52                  <1> 	push	edx
  2861 00002640 50                  <1> 	push	eax ; *
  2862 00002641 89C6                <1> 	mov	esi, eax 
  2863 00002643 31FF                <1> 	xor	edi, edi ; 0
  2864                              <1> dapt_0:
  2865 00002645 AD                  <1> 	lodsd
  2866 00002646 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2867 00002648 7455                <1> 	jz	short dapt_1
  2868                              <1> 	;
  2869 0000264A A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2870                              <1> 				  ; (must be 1)
  2871 0000264C 753F                <1> 	jnz	short dapt_3
  2872                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2873 0000264E 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2874                              <1> 				   ; as child's page ?
  2875 00002652 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2876                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2877                              <1> 	; ECX = page directory entry index (0-1023)
  2878 00002654 53                  <1> 	push	ebx
  2879 00002655 51                  <1> 	push	ecx
  2880 00002656 66C1E102            <1> 	shl	cx, 2 ; *4 
  2881 0000265A 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2882 0000265C 8B0B                <1> 	mov	ecx, [ebx]
  2883 0000265E F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2884 00002661 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2885 00002663 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2886                              <1> 	; EDI = page table entry index (0-1023)
  2887 00002668 89FA                <1> 	mov	edx, edi 
  2888 0000266A 66C1E202            <1> 	shl	dx, 2 ; *4 
  2889 0000266E 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2890 00002670 8B1A                <1> 	mov	ebx, [edx]
  2891 00002672 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2892 00002675 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2893 00002677 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2894 0000267B 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2895 00002680 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2896 00002682 7507                <1> 	jne	short dapt_2	; not same page
  2897                              <1> 				; deallocate the child's page
  2898 00002684 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2899 00002687 59                  <1> 	pop	ecx
  2900 00002688 5B                  <1> 	pop	ebx
  2901 00002689 EB0D                <1> 	jmp	short dapt_4
  2902                              <1> 
  2903                              <1> ; 17/04/2021
  2904                              <1> ; ('dapt_1' is disabled as temporary)
  2905                              <1> ;
  2906                              <1> ;dapt_1:
  2907                              <1> ;	or	eax, eax	; swapped page ?
  2908                              <1> ;	jz	short dapt_5	; no
  2909                              <1> ;				; yes
  2910                              <1> ;	shr	eax, 1
  2911                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2912                              <1> ;				  ; on the swap disk (or in file)
  2913                              <1> ;	jmp	short dapt_5
  2914                              <1> dapt_2:
  2915 0000268B 59                  <1> 	pop	ecx
  2916 0000268C 5B                  <1> 	pop	ebx
  2917                              <1> dapt_3:	
  2918                              <1> 	; 12/07/2016
  2919 0000268D 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2920 00002691 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2921                              <1> 	;
  2922                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2923 00002693 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2924                              <1> dapt_4:
  2925 00002698 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2926                              <1> dapt_1:	; 17/04/2021 (temporary)
  2927                              <1> dapt_5:
  2928 0000269F 47                  <1> 	inc	edi ; page table entry index
  2929 000026A0 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2930 000026A6 729D                <1> 	jb	short dapt_0
  2931                              <1> 	;
  2932 000026A8 58                  <1> 	pop	eax ; *
  2933 000026A9 5A                  <1> 	pop	edx
  2934 000026AA 5F                  <1> 	pop	edi	
  2935 000026AB 5E                  <1> 	pop	esi
  2936                              <1> 	;
  2937                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2938                              <1> 	;retn
  2939                              <1> 
  2940                              <1> deallocate_page:
  2941                              <1> 	; 15/09/2015
  2942                              <1> 	; 28/04/2015
  2943                              <1> 	; 10/03/2015
  2944                              <1> 	; 17/10/2014
  2945                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2946                              <1> 	;
  2947                              <1> 	; INPUT -> 
  2948                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2949                              <1> 	; OUTPUT ->
  2950                              <1> 	;	[free_pages] is increased
  2951                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2952                              <1> 	;	CF = 1 if the page is already deallocated
  2953                              <1> 	; 	       (or not allocated) before.  
  2954                              <1> 	;
  2955                              <1> 	; Modified Registers -> EAX
  2956                              <1> 	;
  2957 000026AC 53                  <1> 	push	ebx
  2958 000026AD 52                  <1> 	push	edx
  2959                              <1> 	;
  2960 000026AE C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2961                              <1> 				     ; 12 bits right
  2962                              <1> 				     ; to get page number
  2963 000026B1 89C2                <1> 	mov	edx, eax
  2964                              <1> 	; 15/09/2015
  2965 000026B3 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2966                              <1> 				     ; (1 allocation bit = 1 page)
  2967                              <1> 				     ; (1 allocation bytes = 8 pages)
  2968 000026B6 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2969                              <1> 				     ; (to get 32 bit position)			
  2970                              <1> 	;
  2971 000026B9 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2972 000026BE 01D3                <1> 	add	ebx, edx
  2973 000026C0 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2974                              <1> 				     ; (allocation bit position)	 
  2975 000026C3 3B15[34680000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2976                              <1> 				     ; than the address in 'next_page' ?
  2977                              <1> 				     ; (next/first free page value)		
  2978 000026C9 7306                <1> 	jnb	short dap_1	     ; no	
  2979 000026CB 8915[34680000]      <1> 	mov	[next_page], edx     ; yes
  2980                              <1> dap_1:
  2981 000026D1 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2982                              <1> 				     ; set relevant bit to 1.
  2983                              <1> 				     ; set CF to the previous bit value	
  2984                              <1> 	;cmc			     ; complement carry flag	
  2985                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2986                              <1> 				     ; if the page is already deallocated
  2987                              <1> 				     ; before.	
  2988 000026D4 FF05[30680000]      <1>         inc     dword [free_pages]
  2989                              <1> dap_2:
  2990 000026DA 5A                  <1> 	pop	edx
  2991 000026DB 5B                  <1> 	pop	ebx
  2992 000026DC C3                  <1> 	retn
  2993                              <1> 
  2994                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2995                              <1> ;;                                                              ;;
  2996                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2997                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2998                              <1> ;;                                                              ;;
  2999                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3000                              <1> 
  3001                              <1> ;;$Revision: 5057 $
  3002                              <1> 
  3003                              <1> 
  3004                              <1> ;;align 4
  3005                              <1> ;;proc alloc_page
  3006                              <1> 
  3007                              <1> ;;        pushfd
  3008                              <1> ;;        cli
  3009                              <1> ;;        push    ebx
  3010                              <1> ;;;//-
  3011                              <1> ;;        cmp     [pg_data.pages_free], 1
  3012                              <1> ;;        jle     .out_of_memory
  3013                              <1> ;;;//-
  3014                              <1> ;;
  3015                              <1> ;;        mov     ebx, [page_start]
  3016                              <1> ;;        mov     ecx, [page_end]
  3017                              <1> ;;.l1:
  3018                              <1> ;;        bsf     eax, [ebx];
  3019                              <1> ;;        jnz     .found
  3020                              <1> ;;        add     ebx, 4
  3021                              <1> ;;        cmp     ebx, ecx
  3022                              <1> ;;        jb      .l1
  3023                              <1> ;;        pop     ebx
  3024                              <1> ;;        popfd
  3025                              <1> ;;        xor     eax, eax
  3026                              <1> ;;        ret
  3027                              <1> ;;.found:
  3028                              <1> ;;;//-
  3029                              <1> ;;        dec     [pg_data.pages_free]
  3030                              <1> ;;        jz      .out_of_memory
  3031                              <1> ;;;//-
  3032                              <1> ;;        btr     [ebx], eax
  3033                              <1> ;;        mov     [page_start], ebx
  3034                              <1> ;;        sub     ebx, sys_pgmap
  3035                              <1> ;;        lea     eax, [eax+ebx*8]
  3036                              <1> ;;        shl     eax, 12
  3037                              <1> ;;;//-       dec [pg_data.pages_free]
  3038                              <1> ;;        pop     ebx
  3039                              <1> ;;        popfd
  3040                              <1> ;;        ret
  3041                              <1> ;;;//-
  3042                              <1> ;;.out_of_memory:
  3043                              <1> ;;        mov     [pg_data.pages_free], 1
  3044                              <1> ;;        xor     eax, eax
  3045                              <1> ;;        pop     ebx
  3046                              <1> ;;        popfd
  3047                              <1> ;;        ret
  3048                              <1> ;;;//-
  3049                              <1> ;;endp
  3050                              <1> 
  3051                              <1> duplicate_page_dir:
  3052                              <1> 	; 21/09/2015
  3053                              <1> 	; 31/08/2015
  3054                              <1> 	; 20/07/2015
  3055                              <1> 	; 28/04/2015
  3056                              <1> 	; 27/04/2015
  3057                              <1> 	; 18/04/2015
  3058                              <1> 	; 12/04/2015
  3059                              <1> 	; 18/10/2014
  3060                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3061                              <1> 	;
  3062                              <1> 	; INPUT -> 
  3063                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3064                              <1> 	;		    page directory.
  3065                              <1> 	; OUTPUT ->
  3066                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3067                              <1> 	;	       page directory.
  3068                              <1> 	;	(New page directory with new page table entries.)
  3069                              <1> 	;	(New page tables with read only copies of the parent's
  3070                              <1> 	;	pages.)
  3071                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3072                              <1> 	;
  3073                              <1> 	; Modified Registers -> none (except EAX)
  3074                              <1> 	;
  3075 000026DD E802FEFFFF          <1> 	call	allocate_page
  3076 000026E2 723E                <1> 	jc	short dpd_err
  3077                              <1> 	;
  3078 000026E4 55                  <1> 	push	ebp ; 20/07/2015
  3079 000026E5 56                  <1> 	push	esi
  3080 000026E6 57                  <1> 	push	edi
  3081 000026E7 53                  <1> 	push	ebx
  3082 000026E8 51                  <1> 	push	ecx
  3083 000026E9 8B35[C46D0000]      <1> 	mov	esi, [u.pgdir]
  3084 000026EF 89C7                <1> 	mov	edi, eax
  3085 000026F1 50                  <1> 	push	eax ; save child's page directory address
  3086                              <1> 	; 31/08/2015
  3087                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3088                              <1> 	; (use same system space for all user page tables) 
  3089 000026F2 A5                  <1> 	movsd
  3090 000026F3 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3091 000026F8 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3092                              <1> dpd_0:	
  3093 000026FD AD                  <1> 	lodsd
  3094                              <1> 	;or	eax, eax
  3095                              <1>         ;jnz     short dpd_1
  3096 000026FE A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3097 00002700 7508                <1> 	jnz	short dpd_1
  3098                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3099 00002702 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3100 00002708 EB0F                <1> 	jmp	short dpd_2
  3101                              <1> dpd_1:	
  3102 0000270A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3103 0000270E 89C3                <1> 	mov	ebx, eax
  3104                              <1> 	; EBX = Parent's page table address
  3105 00002710 E81F000000          <1> 	call	duplicate_page_table
  3106 00002715 720C                <1> 	jc	short dpd_p_err
  3107                              <1> 	; EAX = Child's page table address
  3108 00002717 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3109                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3110                              <1> 			 ; (present, writable, user)
  3111                              <1> dpd_2:
  3112 00002719 AB                  <1> 	stosd
  3113 0000271A E2E1                <1> 	loop	dpd_0
  3114                              <1> 	;
  3115 0000271C 58                  <1> 	pop	eax  ; restore child's page directory address
  3116                              <1> dpd_3:
  3117 0000271D 59                  <1> 	pop	ecx
  3118 0000271E 5B                  <1> 	pop	ebx
  3119 0000271F 5F                  <1> 	pop	edi
  3120 00002720 5E                  <1> 	pop	esi
  3121 00002721 5D                  <1> 	pop	ebp ; 20/07/2015
  3122                              <1> dpd_err:
  3123 00002722 C3                  <1> 	retn
  3124                              <1> dpd_p_err:
  3125                              <1> 	; release the allocated pages missing (recover free space)
  3126 00002723 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3127 00002724 8B1D[C46D0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3128 0000272A E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3129 0000272F 29C0                <1> 	sub	eax, eax ; 0
  3130 00002731 F9                  <1> 	stc
  3131 00002732 EBE9                <1> 	jmp	short dpd_3	
  3132                              <1> 
  3133                              <1> duplicate_page_table:
  3134                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3135                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3136                              <1> 	;	 (temporary modifications)
  3137                              <1> 	; 16/04/2021 (Retro UNIX 386 v2)
  3138                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3139                              <1> 	; 21/09/2015
  3140                              <1> 	; 20/07/2015
  3141                              <1> 	; 05/05/2015
  3142                              <1> 	; 28/04/2015
  3143                              <1> 	; 27/04/2015
  3144                              <1> 	; 18/04/2015
  3145                              <1> 	; 18/10/2014
  3146                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3147                              <1> 	;
  3148                              <1> 	; INPUT -> 
  3149                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3150                              <1> 	;       20/02/2017		 
  3151                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3152                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3153                              <1> 	; OUTPUT ->
  3154                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3155                              <1> 	;	      (with 'read only' attribute of page table entries)
  3156                              <1> 	;	20/02/2017
  3157                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3158                              <1> 	;	
  3159                              <1> 	;	CF = 1 -> error 
  3160                              <1> 	;
  3161                              <1> 	; Modified Registers -> EBP (except EAX)
  3162                              <1> 	;
  3163 00002734 E8ABFDFFFF          <1> 	call	allocate_page
  3164 00002739 725B                <1> 	jc	short dpt_err
  3165                              <1> 	;
  3166 0000273B 50                  <1> 	push	eax ; *
  3167 0000273C 56                  <1> 	push	esi
  3168 0000273D 57                  <1> 	push	edi
  3169 0000273E 52                  <1> 	push	edx
  3170 0000273F 51                  <1> 	push	ecx
  3171                              <1> 	;
  3172 00002740 89DE                <1> 	mov	esi, ebx
  3173 00002742 89C7                <1> 	mov	edi, eax
  3174 00002744 89C2                <1> 	mov	edx, eax
  3175 00002746 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3176                              <1> dpt_0:
  3177 0000274C AD                  <1> 	lodsd
  3178 0000274D 21C0                <1> 	and	eax, eax
  3179 0000274F 7435                <1> 	jz	short dpt_3
  3180 00002751 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3181                              <1> 	; 17/04/2021 (temporary)
  3182 00002753 7503                <1> 	jnz	short dpt_1
  3183                              <1> 	;jz	short dpt_p_err
  3184                              <1> 	; 31/12/2021
  3185 00002755 F9                  <1> 	stc
  3186 00002756 EB39                <1> 	jmp	short dpt_p_err
  3187                              <1> 
  3188                              <1> ; 17/04/2021
  3189                              <1> ; ('reload_page' procedure call is disabled as temporary)
  3190                              <1> ;
  3191                              <1> ;	; 20/07/2015
  3192                              <1> ;	; ebp = virtual (linear) address of the memory page
  3193                              <1> ;	call	reload_page ; 28/04/2015
  3194                              <1> ;	jc	short dpt_p_err
  3195                              <1> dpt_1:
  3196                              <1> 	; 21/09/2015
  3197 00002758 89C1                <1> 	mov	ecx, eax
  3198 0000275A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3199 0000275E F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3200 00002761 751A                <1> 	jnz	short dpt_2
  3201                              <1> 	; Read only (parent) page
  3202                              <1> 	; 	- there is a third process which uses this page -
  3203                              <1> 	; Allocate a new page for the child process
  3204 00002763 E87CFDFFFF          <1> 	call	allocate_page
  3205 00002768 7227                <1> 	jc	short dpt_p_err
  3206 0000276A 57                  <1> 	push	edi
  3207 0000276B 56                  <1> 	push	esi
  3208 0000276C 89CE                <1> 	mov	esi, ecx
  3209 0000276E 89C7                <1> 	mov	edi, eax
  3210 00002770 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3211 00002775 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3212 00002777 5E                  <1> 	pop	esi
  3213 00002778 5F                  <1> 	pop	edi
  3214                              <1> 	;
  3215                              <1> 
  3216                              <1> ; 17/04/2021
  3217                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  3218                              <1> ; 
  3219                              <1> ;	push	ebx
  3220                              <1> ;	push	eax
  3221                              <1> ;	; 20/07/2015
  3222                              <1> ;	mov	ebx, ebp
  3223                              <1> ;	; ebx = virtual (linear) address of the memory page
  3224                              <1> ;	call	add_to_swap_queue
  3225                              <1> ;	pop	eax
  3226                              <1> ;	pop	ebx
  3227                              <1> 
  3228                              <1> 	; 21/09/2015
  3229 00002779 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3230                              <1> 		; user + writable + present page
  3231 0000277B EB09                <1> 	jmp	short dpt_3
  3232                              <1> dpt_2:
  3233                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3234 0000277D 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3235                              <1> 		    ; (read only page!)
  3236 0000277F 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3237 00002782 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3238                              <1> dpt_3:
  3239 00002786 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3240                              <1> 	;
  3241 00002787 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3242                              <1> 	;
  3243 0000278D 39D7                <1> 	cmp	edi, edx
  3244 0000278F 72BB                <1> 	jb	short dpt_0
  3245                              <1> dpt_p_err:
  3246 00002791 59                  <1> 	pop	ecx
  3247 00002792 5A                  <1> 	pop	edx
  3248 00002793 5F                  <1> 	pop	edi
  3249 00002794 5E                  <1> 	pop	esi
  3250 00002795 58                  <1> 	pop	eax ; *
  3251                              <1> dpt_err:
  3252 00002796 C3                  <1> 	retn
  3253                              <1> 
  3254                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3255                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3256                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3257                              <1> 	;	 (temporary modifications)
  3258                              <1> 	; 21/09/2015
  3259                              <1> 	; 19/09/2015
  3260                              <1> 	; 17/09/2015
  3261                              <1> 	; 28/08/2015
  3262                              <1> 	; 20/07/2015
  3263                              <1> 	; 28/06/2015
  3264                              <1> 	; 03/05/2015
  3265                              <1> 	; 30/04/2015
  3266                              <1> 	; 18/04/2015
  3267                              <1> 	; 12/04/2015
  3268                              <1> 	; 30/10/2014
  3269                              <1> 	; 11/09/2014
  3270                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3271                              <1> 	;
  3272                              <1> 	; Note: This is not an interrupt/exception handler.
  3273                              <1> 	;	This is a 'page fault remedy' subroutine 
  3274                              <1> 	;	which will be called by standard/uniform
  3275                              <1> 	;	exception handler.
  3276                              <1> 	;
  3277                              <1> 	; INPUT -> 
  3278                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3279                              <1> 	;
  3280                              <1> 	;	cr2 = the virtual (linear) address 
  3281                              <1> 	;	      which has caused to page fault (19/09/2015)
  3282                              <1> 	;
  3283                              <1> 	; OUTPUT ->
  3284                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3285                              <1> 	;	EAX = 0 -> no error
  3286                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3287                              <1> 	;
  3288                              <1> 	; Modified Registers -> none (except EAX)
  3289                              <1> 	;	
  3290                              <1>         ;
  3291                              <1>         ; ERROR CODE:
  3292                              <1> 	;	 31  .....	4   3	2   1	0
  3293                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3294                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3295                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3296                              <1> 	;
  3297                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3298                              <1>     	;		a page-protection violation. When not set,
  3299                              <1> 	;		it was caused by a non-present page.
  3300                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3301                              <1> 	;		a page write. When not set, it was caused
  3302                              <1> 	;		by a page read.
  3303                              <1> 	; U : USER    -	When set, the page fault was caused 
  3304                              <1> 	;		while CPL = 3. 
  3305                              <1> 	;		This does not necessarily mean that
  3306                              <1> 	;		the page fault was a privilege violation.
  3307                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3308                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3309                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3310                              <1> 	;     FETCH	an instruction fetch
  3311                              <1> 	;
  3312                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3313                              <1> 	;  31               22                  12 11                    0
  3314                              <1> 	; +-------------------+-------------------+-----------------------+
  3315                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3316                              <1>        	; +-------------------+-------------------+-----------------------+
  3317                              <1> 	;
  3318                              <1> 
  3319                              <1> 	;; CR3 REGISTER (Control Register 3)
  3320                              <1> 	;  31                                   12             5 4 3 2   0
  3321                              <1> 	; +---------------------------------------+-------------+---+-----+
  3322                              <1>       	; |                                       |  		|P|P|     |
  3323                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3324                              <1>       	; |                                       | 		|D|T|     |
  3325                              <1>    	; +---------------------------------------+-------------+---+-----+
  3326                              <1> 	;
  3327                              <1> 	;	PWT    - WRITE THROUGH
  3328                              <1> 	;	PCD    - CACHE DISABLE		
  3329                              <1> 	;
  3330                              <1> 	;
  3331                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3332                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3333                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3334                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3335                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3336                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3337                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3338                              <1> 	;
  3339                              <1>         ;       P      - PRESENT
  3340                              <1>         ;       R/W    - READ/WRITE
  3341                              <1>         ;       U/S    - USER/SUPERVISOR
  3342                              <1> 	;	PWT    - WRITE THROUGH
  3343                              <1> 	;	PCD    - CACHE DISABLE	
  3344                              <1> 	;	A      - ACCESSED	
  3345                              <1>         ;       D      - DIRTY (IGNORED)
  3346                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3347                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3348                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3349                              <1> 	;
  3350                              <1> 	;
  3351                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3352                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3353                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3354                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3355                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3356                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3357                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3358                              <1> 	;
  3359                              <1>         ;       P      - PRESENT
  3360                              <1>         ;       R/W    - READ/WRITE
  3361                              <1>         ;       U/S    - USER/SUPERVISOR
  3362                              <1> 	;	PWT    - WRITE THROUGH
  3363                              <1> 	;	PCD    - CACHE DISABLE	
  3364                              <1> 	;	A      - ACCESSED	
  3365                              <1>         ;       D      - DIRTY
  3366                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3367                              <1> 	;	G      - GLOBAL	 
  3368                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3369                              <1> 	;
  3370                              <1> 	;
  3371                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3372                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3373                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3374                              <1>       	; |                                       |     | | | | | | |U|R| |
  3375                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3376                              <1>       	; |                                       |     | | | | | | |S|W| |
  3377                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3378                              <1> 	;
  3379                              <1>         ;       P      - PRESENT
  3380                              <1>         ;       R/W    - READ/WRITE
  3381                              <1>         ;       U/S    - USER/SUPERVISOR
  3382                              <1>         ;       D      - DIRTY
  3383                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3384                              <1> 	;
  3385                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3386                              <1> 	;
  3387                              <1> 	;
  3388                              <1> 	;; Invalid Page Table Entry
  3389                              <1> 	; 31                                                           1 0
  3390                              <1>       	; +-------------------------------------------------------------+-+
  3391                              <1>       	; |                                                             | |
  3392                              <1>       	; |                          AVAILABLE                          |0|
  3393                              <1>       	; |                                                             | |
  3394                              <1>       	; +-------------------------------------------------------------+-+
  3395                              <1> 	;
  3396                              <1> 
  3397 00002797 53                  <1> 	push	ebx
  3398 00002798 52                  <1> 	push	edx
  3399 00002799 51                  <1> 	push	ecx
  3400                              <1> 	;
  3401                              <1> 	; 21/09/2015 (debugging)
  3402 0000279A FF05[DC6D0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3403 000027A0 FF05[DC680000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3404                              <1> 	; 28/06/2015
  3405                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3406 000027A6 8A15[D4680000]      <1> 	mov	dl, [error_code]
  3407                              <1> 	;
  3408 000027AC F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3409                              <1> 			; sign
  3410 000027AF 7416                <1> 	jz	short pfh_alloc_np
  3411                              <1> 	; 
  3412                              <1> 	; If it is not a 'write on read only page' type page fault
  3413                              <1> 	; major page fault error with minor reason must be returned without 
  3414                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3415                              <1> 	; after return here!
  3416                              <1> 	; Page fault will be remedied, by copying page contents
  3417                              <1> 	; to newly allocated page with write permission;
  3418                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3419                              <1> 	; used for working with minimum possible memory usage. 
  3420                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3421                              <1> 	; process with 'read only' flag. If the child process attempts to
  3422                              <1> 	; write on these read only pages, page fault will be directed here
  3423                              <1> 	; for allocating a new page with same data/content. 
  3424                              <1> 	;
  3425                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3426                              <1> 	; will not force to separate CODE and DATA space 
  3427                              <1> 	; in a process/program... 
  3428                              <1> 	; CODE segment/section may contain DATA!
  3429                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3430                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3431                              <1> 	;	
  3432 000027B1 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3433                              <1> 			; sign
  3434 000027B4 744F                <1>         jz	short pfh_p_err
  3435                              <1> 	; 31/08/2015
  3436 000027B6 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3437                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3438 000027B9 744A                <1>         jz	short pfh_pv_err
  3439                              <1> 	;
  3440                              <1> 	; make a new page and copy the parent's page content
  3441                              <1> 	; as the child's new page content
  3442                              <1> 	;
  3443 000027BB 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3444                              <1> 			 ; which has caused to page fault
  3445 000027BE E87C000000          <1> 	call 	copy_page
  3446 000027C3 7239                <1>         jc	short pfh_im_err ; insufficient memory
  3447                              <1> 	;
  3448 000027C5 EB72                <1>         jmp     pfh_cpp_ok
  3449                              <1> 	;
  3450                              <1> pfh_alloc_np:
  3451 000027C7 E818FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3452 000027CC 7230                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3453                              <1> pfh_chk_cpl:
  3454                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3455                              <1> 		; (Lower 12 bits are ZERO, because 
  3456                              <1> 		;	the address is on a page boundary)
  3457 000027CE 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3458 000027D1 7505                <1> 	jnz	short pfh_um
  3459                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3460 000027D3 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3461                              <1> 			 ; of the current/active page directory
  3462                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3463                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3464 000027D6 EB06                <1> 	jmp	short pfh_get_pde
  3465                              <1> 	;
  3466                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3467 000027D8 8B1D[C46D0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3468                              <1> 			; Physical address of the USER's page directory
  3469                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3470                              <1> pfh_get_pde:
  3471 000027DE 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3472 000027E1 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3473                              <1> 			 ; which has been caused to page fault
  3474                              <1> 			 ;
  3475 000027E4 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3476 000027E7 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3477                              <1> 	;
  3478 000027EA 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3479 000027EC 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3480 000027EE F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3481 000027F1 741A                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3482                              <1> 			  	  ; set/validate page directory entry
  3483 000027F3 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3484 000027F8 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3485 000027FA 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3486 000027FC EB25                <1> 	jmp	short pfh_get_pte
  3487                              <1> 
  3488                              <1> 	; 31/12/2021 (short jump)
  3489                              <1> pfh_im_err:
  3490 000027FE B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3491                              <1> 			; Major (Primary) Error: Page Fault
  3492                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3493 00002803 EB36                <1> 	jmp	short pfh_err_retn
  3494                              <1> 
  3495                              <1> 	; 31/12/2021
  3496                              <1> pfh_p_err: ; 09/03/2015
  3497                              <1> pfh_pv_err:
  3498                              <1> 	; Page fault was caused by a protection-violation
  3499 00002805 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3500                              <1> 			; Major (Primary) Error: Page Fault
  3501                              <1> 			; Minor (Secondary) Error: Protection violation !
  3502 0000280A F9                  <1> 	stc
  3503 0000280B EB2E                <1> 	jmp	short pfh_err_retn
  3504                              <1> 
  3505                              <1> pfh_set_pde:
  3506                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3507                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3508                              <1> 	;
  3509 0000280D 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3510 0000280F 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3511 00002811 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3512 00002813 89C3                <1> 	mov	ebx, eax
  3513 00002815 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3514 0000281A 72E2                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3515                              <1> pfh_spde_1:
  3516                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3517 0000281C 89C1                <1> 	mov	ecx, eax
  3518 0000281E E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3519                              <1> pfh_get_pte:
  3520 00002823 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3521                              <1> 			 ; which has been caused to page fault
  3522 00002826 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3523 00002828 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3524                              <1> 			 ; higher 20 bits of the page fault address 
  3525 0000282B 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3526 00002830 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3527 00002833 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3528                              <1> ; 17/04/2021 temporary
  3529                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3530                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3531                              <1> ; 17/04/2021
  3532                              <1> ; ('swap_in' procedure call has been disabled as temporary)
  3533                              <1> ;
  3534                              <1> ;	and	eax, eax
  3535                              <1> ;	jz	short pfh_gpte_1
  3536                              <1> ;	; 20/07/2015
  3537                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3538                              <1> ;	push	ebp ; 20/07/2015
  3539                              <1> ;	mov	ebp, cr2
  3540                              <1> ;		; ECX = physical address of the page table entry
  3541                              <1> ;		; EBX = Memory page address (physical!)
  3542                              <1> ;		; EAX = Swap disk (offset) address
  3543                              <1> ;		; EBP = virtual address (page fault address)
  3544                              <1> ;	call	swap_in
  3545                              <1> ;	pop	ebp
  3546                              <1> ;	jc      short pfh_err_retn
  3547                              <1> ;	xchg	ecx, ebx
  3548                              <1> ;		; EBX = physical address of the page table entry
  3549                              <1> ;		; ECX = new page
  3550                              <1> pfh_gpte_1:
  3551 00002835 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3552 00002837 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3553                              <1> pfh_cpp_ok:
  3554                              <1> ; 17/04/2021
  3555                              <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary)
  3556                              <1> ;
  3557                              <1> ;	; 20/07/2015
  3558                              <1> ;	mov	ebx, cr2
  3559                              <1> ;	call 	add_to_swap_queue
  3560                              <1> 	;
  3561                              <1> 	; The new PTE (which contains the new page) will be added to 
  3562                              <1> 	; the swap queue, here. 
  3563                              <1> 	; (Later, if memory will become insufficient, 
  3564                              <1> 	; one page will be swapped out which is at the head of 
  3565                              <1> 	; the swap queue by using FIFO and access check methods.)
  3566                              <1> 	;
  3567 00002839 31C0                <1> 	xor	eax, eax  ; 0
  3568                              <1> 	;
  3569                              <1> pfh_err_retn:
  3570 0000283B 59                  <1> 	pop	ecx
  3571 0000283C 5A                  <1> 	pop	edx
  3572 0000283D 5B                  <1> 	pop	ebx
  3573 0000283E C3                  <1> 	retn 
  3574                              <1> 	
  3575                              <1> copy_page:
  3576                              <1> 	; 16/04/2021
  3577                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3578                              <1> 	; 22/09/2015
  3579                              <1> 	; 21/09/2015
  3580                              <1> 	; 19/09/2015
  3581                              <1> 	; 07/09/2015
  3582                              <1> 	; 31/08/2015
  3583                              <1> 	; 20/07/2015
  3584                              <1> 	; 05/05/2015
  3585                              <1> 	; 03/05/2015
  3586                              <1> 	; 18/04/2015
  3587                              <1> 	; 12/04/2015
  3588                              <1> 	; 30/10/2014
  3589                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3590                              <1> 	;
  3591                              <1> 	; INPUT -> 
  3592                              <1> 	;	EBX = Virtual (linear) address of source page
  3593                              <1> 	;	     (Page fault address)
  3594                              <1> 	; OUTPUT ->
  3595                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3596                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3597                              <1> 	;	EAX = 0 (CF = 1) 
  3598                              <1> 	;		if there is not a free page to be allocated
  3599                              <1> 	;	(page content of the source page will be copied
  3600                              <1> 	;	onto the target/new page) 	
  3601                              <1> 	;
  3602                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3603                              <1> 	;
  3604                              <1> 
  3605                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3606                              <1> 	; INPUT: 
  3607                              <1> 	;	EBX = Virtual (linear) address of source page
  3608                              <1> 	;	     (Page fault address)
  3609                              <1> 	; OUTPUT:
  3610                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3611                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3612                              <1> 	;	EAX = 0 (CF = 1) 
  3613                              <1> 	;		if there is not a free page to be allocated
  3614                              <1> 	;	(page content of the source page will be copied
  3615                              <1> 	;	onto the target/new page) 	
  3616                              <1> 	;
  3617                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3618                              <1> 	
  3619 0000283F 56                  <1> 	push	esi ; *
  3620 00002840 57                  <1> 	push	edi ; **
  3621                              <1> 	; 16/04/2021
  3622                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3623                              <1> 	;push	ebx ; ***
  3624                              <1> 	;push	ecx ; ****
  3625 00002841 31F6                <1> 	xor 	esi, esi
  3626 00002843 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3627 00002846 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3628 00002848 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3629 0000284B 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3630 0000284E 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3631 00002850 031D[C46D0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3632 00002856 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3633 00002858 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3634 0000285C 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3635 0000285E 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3636 00002864 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3637 00002868 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3638                              <1> 	; 07/09/2015
  3639 0000286A 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3640                              <1> 				     ; read only page as a child process?)	
  3641 0000286F 7509                <1> 	jnz	short cpp_0 ; yes
  3642 00002871 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3643 00002873 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3644 00002878 EB32                <1> 	jmp	short cpp_1
  3645                              <1> cpp_0:
  3646 0000287A 89FE                <1> 	mov	esi, edi
  3647 0000287C 0335[C86D0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3648 00002882 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3649 00002884 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3650 00002888 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3651 0000288A 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3652 00002890 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3653 00002894 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3654 00002896 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3655                              <1> 	; 21/09/2015
  3656 00002898 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3657 0000289A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3658                              <1> 	;
  3659 0000289E F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3660 000028A1 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3661                              <1> 	;
  3662 000028A3 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3663 000028A8 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3664 000028AA 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3665                              <1> 			    ; Convert child's page to writable page
  3666                              <1> cpp_1:
  3667 000028AC E833FCFFFF          <1> 	call	allocate_page
  3668 000028B1 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3669 000028B3 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3670 000028B5 7405                <1> 	jz	short cpp_2
  3671                              <1> 		; Convert read only page to writable page 
  3672                              <1> 		;(for the parent of the current process)
  3673                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3674                              <1> 	; 22/09/2015
  3675 000028B7 890E                <1> 	mov	[esi], ecx
  3676 000028B9 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3677                              <1> 				 ; 1+2+4 = 7
  3678                              <1> cpp_2:
  3679 000028BC 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3680                              <1> 	; 07/09/2015
  3681 000028BE 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3682 000028C0 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3683 000028C5 F3A5                <1> 	rep	movsd ; 31/08/2015
  3684                              <1> cpp_3:		
  3685 000028C7 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3686 000028C9 8903                <1> 	mov	[ebx], eax ; Update PTE
  3687 000028CB 28C0                <1> 	sub	al, al ; clear attributes
  3688                              <1> cpp_4:
  3689                              <1> 	; 16/04/2021
  3690                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3691                              <1> 	;pop	ecx ; ****
  3692                              <1> 	;pop	ebx ; ***
  3693 000028CD 5F                  <1> 	pop	edi ; **
  3694 000028CE 5E                  <1> 	pop	esi ; *
  3695 000028CF C3                  <1> 	retn
  3696                              <1> 
  3697                              <1> ;; 28/04/2015
  3698                              <1> ;; 24/10/2014
  3699                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3700                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3701                              <1> ;;
  3702                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3703                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3704                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3705                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3706                              <1> ;;
  3707                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3708                              <1> ;;
  3709                              <1> ;; Method:
  3710                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3711                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3712                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3713                              <1> ;;	When a new page is being allocated, swap queue is updated
  3714                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3715                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3716                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3717                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3718                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3719                              <1> ;;	offset value becomes it's previous offset value - 4.
  3720                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3721                              <1> ;;	the queue/list is not shifted.
  3722                              <1> ;;	After the queue/list shift, newly allocated page is added
  3723                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3724                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3725                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3726                              <1> ;;	
  3727                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3728                              <1> ;;	the first non-accessed, writable page in the list, 
  3729                              <1> ;;	from the head to the tail. The list is shifted to left 
  3730                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3731                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3732                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3733                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3734                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3735                              <1> ;;	procedure will be failed)...
  3736                              <1> ;;
  3737                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3738                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3739                              <1> ;;	(PTE) will be added to the tail of the queue after
  3740                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3741                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3742                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3743                              <1> ;;
  3744                              <1> ;;
  3745                              <1> ;;	
  3746                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3747                              <1> ;;
  3748                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3749                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3750                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3751                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3752                              <1> ;;
  3753                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3754                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3755                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3756                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3757                              <1> ;; 		 (entire swap space must be accessed by using
  3758                              <1> ;;		 31 bit offset address) 
  3759                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3760                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3761                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3762                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3763                              <1> ;;
  3764                              <1> ;; 					
  3765                              <1> ;; Method:
  3766                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3767                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3768                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3769                              <1> ;;	Swapping out is performed by using swap page queue.
  3770                              <1> ;;
  3771                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3772                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3773                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3774                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3775                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3776                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3777                              <1> ;;	calculated by adding offset value to the swap partition's 
  3778                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3779                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3780                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3781                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3782                              <1> ;;	is in a partitioned virtual hard disk.) 
  3783                              <1> ;;
  3784                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3785                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3786                              <1> ;;
  3787                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3788                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3789                              <1> ;;
  3790                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3791                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3792                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3793                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3794                              <1> ;;	it means relevant (respective) block is in use, and, 
  3795                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3796                              <1> ;;      swap disk/file block is free.
  3797                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3798                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3799                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3800                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3801                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3802                              <1> ;;	------------------------------------------------------------
  3803                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3804                              <1> ;;	------------------------------------------------------------
  3805                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3806                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3807                              <1> ;;
  3808                              <1> ;;	..............................................................
  3809                              <1> ;;
  3810                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3811                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3812                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3813                              <1> ;;	position with value of 1 on the table is converted to swap
  3814                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3815                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3816                              <1> ;;	number of physical swap disk or virtual swap disk)
  3817                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3818                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3819                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3820                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3821                              <1> ;;	If disk write procedure returns with error or free count of 
  3822                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3823                              <1> ;;	'insufficient memory error' (cf=1). 
  3824                              <1> ;;
  3825                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3826                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3827                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3828                              <1> ;;	free blocks after a disk write error. It will return to 
  3829                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3830                              <1> ;;
  3831                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3832                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3833                              <1> ;;	address (cf=0). 
  3834                              <1> ;;
  3835                              <1> ;;	..............................................................
  3836                              <1> ;;
  3837                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3838                              <1> ;;	file sectors at specified memory page. Then page allocation
  3839                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3840                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3841                              <1> ;;	to do, except to terminate the process which is the owner of
  3842                              <1> ;;	the swapped page.
  3843                              <1> ;;
  3844                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3845                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3846                              <1> ;;	updates [swpd_first] pointer if it is required.
  3847                              <1> ;;
  3848                              <1> ;;	..............................................................	 
  3849                              <1> ;;
  3850                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3851                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3852                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3853                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3854                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3855                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3856                              <1> ;;
  3857                              <1> 
  3858                              <1> ; 17/04/2021
  3859                              <1> ; ('swap_in' procedure call is disabled as temporary)
  3860                              <1> 
  3861                              <1> ; 30/11/2021 - temporary !
  3862                              <1> ;swap_in:
  3863                              <1> 	; 31/08/2015
  3864                              <1> 	; 20/07/2015
  3865                              <1> 	; 28/04/2015
  3866                              <1> 	; 18/04/2015
  3867                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3868                              <1> 	;
  3869                              <1> 	; INPUT -> 
  3870                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3871                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3872                              <1> 	;	EAX = Offset Address for the swapped page on the
  3873                              <1> 	;	      swap disk or in the swap file.
  3874                              <1> 	;
  3875                              <1> 	; OUTPUT ->
  3876                              <1> 	;	EAX = 0 if loading at memory has been successful
  3877                              <1> 	;
  3878                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3879                              <1> 	;		  or sector not present or drive not ready
  3880                              <1> 	;	     EAX = Error code
  3881                              <1> 	;	     [u.error] = EAX 
  3882                              <1> 	;		       = The last error code for the process
  3883                              <1> 	;		         (will be reset after returning to user)	  
  3884                              <1> 	;
  3885                              <1> 	; Modified Registers -> EAX
  3886                              <1> 	;
  3887                              <1> 
  3888                              <1> ;       cmp     dword [swp_drv], 0
  3889                              <1> ;	jna	short swpin_dnp_err
  3890                              <1> ;
  3891                              <1> ;	cmp	eax, [swpd_size]
  3892                              <1> ;	jnb	short swpin_snp_err
  3893                              <1> ;
  3894                              <1> ;	push	esi
  3895                              <1> ;	push	ebx
  3896                              <1> ;	push	ecx
  3897                              <1> ;	mov	esi, [swp_drv]	
  3898                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3899                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3900                              <1> ;		; size different than 512 bytes, logical disk sector
  3901                              <1> ;		; size is 512 bytes and disk reading procedure
  3902                              <1> ;		; will be performed for reading 4096 bytes
  3903                              <1> ;		; (2*2048, 8*512). 
  3904                              <1> ;	; ESI = Logical disk description table address
  3905                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3906                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3907                              <1> ;	; ECX = Sector count ; 8 sectors
  3908                              <1> ;	push	eax
  3909                              <1> ;	call	logical_disk_read
  3910                              <1> ;	pop	eax
  3911                              <1> ;	jnc	short swpin_read_ok
  3912                              <1> ;	;
  3913                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3914                              <1> ;	mov	[u.error], eax
  3915                              <1> ;	jmp	short swpin_retn
  3916                              <1> ;	;
  3917                              <1> ;swpin_read_ok:
  3918                              <1> ;	; EAX = Offset address (logical sector number)
  3919                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3920                              <1> ;	;
  3921                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3922                              <1> ;	; 20/07/2015
  3923                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3924                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3925                              <1> ;	mov	bl, [u.uno] ; current process number
  3926                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3927                              <1> ;	call	swap_queue_shift
  3928                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3929                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3930                              <1> ;	; zf = 1
  3931                              <1> ;swpin_retn:
  3932                              <1> ;	pop	ecx
  3933                              <1> ;	pop	ebx
  3934                              <1> ;	pop	esi
  3935                              <1> ;	retn
  3936                              <1> ;
  3937                              <1> ;swpin_dnp_err:
  3938                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3939                              <1> ;swpin_err_retn:
  3940                              <1> ;	mov	[u.error], eax
  3941                              <1> ;	stc
  3942                              <1> ;	retn
  3943                              <1> ;
  3944                              <1> ;swpin_snp_err:
  3945                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3946                              <1> ;	jmp	short swpin_err_retn
  3947                              <1> 
  3948                              <1> ; 17/04/2021
  3949                              <1> ; ('swap_out' procedure call is disabled as temporary)
  3950                              <1> 
  3951                              <1> ; 30/11/2021 - temporary !
  3952                              <1> ;swap_out:
  3953                              <1> 	; 10/06/2016
  3954                              <1> 	; 07/06/2016
  3955                              <1>         ; 23/05/2016
  3956                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3957                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3958                              <1> 	;
  3959                              <1> 	; INPUT -> 
  3960                              <1> 	;	none
  3961                              <1> 	;
  3962                              <1> 	; OUTPUT ->
  3963                              <1> 	;	EAX = Physical page address (which is swapped out
  3964                              <1> 	;	      for allocating a new page)
  3965                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3966                              <1> 	;		  or sector not present or drive not ready
  3967                              <1> 	;	     EAX = Error code
  3968                              <1> 	;	     [u.error] = EAX 
  3969                              <1> 	;		       = The last error code for the process
  3970                              <1> 	;		         (will be reset after returning to user)	  
  3971                              <1> 	;
  3972                              <1> 	; Modified Registers -> none (except EAX)
  3973                              <1> 	;
  3974                              <1> 
  3975                              <1> ;	cmp 	word [swpq_count], 1
  3976                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3977                              <1> ;
  3978                              <1> ;       ;cmp    dword [swp_drv], 1
  3979                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3980                              <1> ;
  3981                              <1> ;       cmp     dword [swpd_free], 1
  3982                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3983                              <1> ;
  3984                              <1> ;	push	ebx ; *
  3985                              <1> ;swpout_1:
  3986                              <1> ;	; 10/06/2016
  3987                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3988                              <1> ;	call	swap_queue_shift
  3989                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3990                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3991                              <1> ;				       ; pointer in the swap queue
  3992                              <1> ;	; EAX = PTE value of the page
  3993                              <1> ;	; EBX = PTE address of the page
  3994                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3995                              <1> ;	;
  3996                              <1> ;	; 07/06/2016
  3997                              <1> ;	; 19/05/2016
  3998                              <1> ;	; check this page is in timer events or not
  3999                              <1> ;	
  4000                              <1> ;swpout_timer_page_0:
  4001                              <1> ;	push	edx ; **
  4002                              <1> ;
  4003                              <1> ;	; 07/06/2016
  4004                              <1> ;	cmp	byte [timer_events], 0 
  4005                              <1> ;	jna	short swpout_2
  4006                              <1> ;	;
  4007                              <1> ;	mov	dl, [timer_events]
  4008                              <1> ;
  4009                              <1> ;	push	ecx ; ***
  4010                              <1> ;	push	ebx ; ****
  4011                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4012                              <1> ;			       ; structures 
  4013                              <1> ;swpout_timer_page_1:
  4014                              <1> ;	mov	cl, [ebx]
  4015                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4016                              <1> ;	jz	short swpout_timer_page_3
  4017                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4018                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4019                              <1> ;				; of the response byte address, to
  4020                              <1> ;				; get beginning of the page address)
  4021                              <1> ;	cmp	eax, ecx
  4022                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4023                              <1> ;	
  4024                              <1> ;	; !same page!
  4025                              <1> ;	;
  4026                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4027                              <1> ;	; This page will be used by the kernel to put timer event
  4028                              <1> ;	; response (signal return) byte at the requested address;
  4029                              <1> ;	; in order to prevent a possible wrong write (while
  4030                              <1> ;	; this page is swapped out) on physical memory,
  4031                              <1> ;	; we must protect this page against to be swapped out!
  4032                              <1> ;	;
  4033                              <1> ;	pop	ebx ; ****
  4034                              <1> ;	pop	ecx ; ***
  4035                              <1> ;	pop	edx ; **
  4036                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4037                              <1> ; 
  4038                              <1> ;swpout_timer_page_2:
  4039                              <1> ;	; 07/06/2016
  4040                              <1> ;	dec	dl
  4041                              <1> ;	jz	short swpout_timer_page_4
  4042                              <1> ;swpout_timer_page_3:
  4043                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4044                              <1> ;	;jnb	short swpout_timer_page_4
  4045                              <1> ;	add	ebx, 16
  4046                              <1> ;	jmp	short swpout_timer_page_1	
  4047                              <1> ;
  4048                              <1> ;swpout_timer_page_4:
  4049                              <1> ;	pop	ebx ; ****
  4050                              <1> ;	pop	ecx ; ***
  4051                              <1> ;swpout_2:
  4052                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4053                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4054                              <1> ;	;
  4055                              <1> ;	call	link_swap_block
  4056                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4057                              <1> ;				       ; because [swpd_free] value
  4058                              <1> ;				       ; was checked at the beginging. 	
  4059                              <1> ;	pop	edx ; **
  4060                              <1> ;	pop	ebx ; *
  4061                              <1> ;	jmp	short swpout_nfspc_err 
  4062                              <1> ;swpout_3:
  4063                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4064                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4065                              <1> ;	;	
  4066                              <1> ;	push	esi ; **
  4067                              <1> ;	push	ecx ; ***
  4068                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4069                              <1> ;	mov	esi, [swp_drv]	
  4070                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4071                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4072                              <1> ;		; size different than 512 bytes, logical disk sector
  4073                              <1> ;		; size is 512 bytes and disk writing procedure
  4074                              <1> ;		; will be performed for writing 4096 bytes
  4075                              <1> ;		; (2*2048, 8*512). 
  4076                              <1> ;	; ESI = Logical disk description table address
  4077                              <1> ;	; EBX = Buffer (Page) address
  4078                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4079                              <1> ;	; ECX = Sector count ; 8 sectors
  4080                              <1> ;	; edx = PTE address
  4081                              <1> ;	call	logical_disk_write
  4082                              <1> ;	; edx = PTE address
  4083                              <1> ;	pop	ecx ; sector address	
  4084                              <1> ;	jnc	short swpout_write_ok
  4085                              <1> ;	;
  4086                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4087                              <1> ;swpout_dw_err:
  4088                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4089                              <1> ;	mov	[u.error], eax
  4090                              <1> ;	jmp	short swpout_retn
  4091                              <1> ;	;
  4092                              <1> ;swpout_write_ok:
  4093                              <1> ;	; EBX = Buffer (page) address
  4094                              <1> ;	; EDX = Page Table Entry address
  4095                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4096                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4097                              <1> ;	mov 	[edx], ecx 
  4098                              <1> ;		; bit 0 = 0 (swapped page)
  4099                              <1> ;	mov	eax, ebx
  4100                              <1> ;swpout_retn:
  4101                              <1> ;	pop	ecx ; ***
  4102                              <1> ;	pop	esi ; **
  4103                              <1> ;	pop	ebx ; *
  4104                              <1> ;	retn
  4105                              <1> ;
  4106                              <1> ;;swpout_dnp_err:
  4107                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4108                              <1> ;;	jmp	short swpout_err_retn
  4109                              <1> ;swpout_nfspc_err:
  4110                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4111                              <1> ;swpout_err_retn:
  4112                              <1> ;	mov	[u.error], eax
  4113                              <1> ;	;stc
  4114                              <1> ;	retn
  4115                              <1> ;swpout_npts_err:
  4116                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4117                              <1> ;	pop	ebx
  4118                              <1> ;	jmp	short swpout_err_retn
  4119                              <1> ;swpout_im_err:
  4120                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4121                              <1> ;	jmp	short swpout_err_retn
  4122                              <1> 
  4123                              <1> ; 17/04/2021
  4124                              <1> ; ('swap_queue_shift' procedure call is disabled as temporary)
  4125                              <1> 
  4126                              <1> ; 30/11/2021 - temporary !
  4127                              <1> ;swap_queue_shift:
  4128                              <1> 	; 26/03/2017
  4129                              <1> 	; 10/06/2016
  4130                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4131                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4132                              <1> 	;
  4133                              <1> 	; INPUT ->
  4134                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4135                              <1> 	;	      and process number combination (bit 0 to 11)
  4136                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4137                              <1> 	;	
  4138                              <1> 	; OUTPUT ->
  4139                              <1> 	;	If EBX input > 0 
  4140                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4141                              <1> 	; 	   from the tail to the head, up to entry offset
  4142                              <1> 	; 	   which points to EBX input value or nothing
  4143                              <1> 	;	   to do if EBX value is not found on the queue.
  4144                              <1> 	;	   (The entry -with EBX value- will be removed
  4145                              <1> 	;	   from the queue if it is found.)
  4146                              <1> 	;
  4147                              <1> 	;	   EAX = 0		
  4148                              <1> 	;
  4149                              <1> 	;	If EBX input = 0
  4150                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4151                              <1> 	; 	   from the tail to the head, if the PTE address
  4152                              <1> 	;	   which is pointed in head of the queue is marked
  4153                              <1> 	;	   as "accessed" or it is marked as "non present".
  4154                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4155                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4156                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4157                              <1> 	;	   -without dropping pointer of the PTE from 
  4158                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4159                              <1> 	;	   Pointer in the head will be moved into the tail,
  4160                              <1> 	;	   other PTEs will be shifted on head direction.)
  4161                              <1> 	;
  4162                              <1> 	;	   Swap queue will be shifted up to the first
  4163                              <1> 	;	   'present' or 'non accessed' page will be found
  4164                              <1> 	;	   (as pointed) on the queue head (then it will be
  4165                              <1>         ;          removed/dropped from the queue).
  4166                              <1> 	;
  4167                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4168                              <1> 	;		 (it's pointer -virtual address-) dropped
  4169                              <1> 	;		 (removed) from swap queue.
  4170                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4171                              <1> 	;	         which is (it's pointer -virtual address-)
  4172                              <1> 	;		 dropped (removed) from swap queue.
  4173                              <1> 	;
  4174                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4175                              <1> 	;
  4176                              <1> 	; Modified Registers -> EAX, EBX
  4177                              <1> 	;
  4178                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4179                              <1> ;	and	ax, ax
  4180                              <1> ;	jz	short swpqs_retn
  4181                              <1> ;	push	edi
  4182                              <1> ;	push	esi
  4183                              <1> ;	push	ecx
  4184                              <1> ;	mov	esi, swap_queue
  4185                              <1> ;	mov	ecx, eax
  4186                              <1> ;	or	ebx, ebx
  4187                              <1> ;	jz	short swpqs_7
  4188                              <1> ;swpqs_1:
  4189                              <1> ;	lodsd
  4190                              <1> ;	cmp	eax, ebx
  4191                              <1> ;	je	short swpqs_2
  4192                              <1> ;	loop	swpqs_1
  4193                              <1> ;	; 10/06/2016
  4194                              <1> ;	sub	eax, eax 
  4195                              <1> ;	jmp	short swpqs_6
  4196                              <1> ;swpqs_2:
  4197                              <1> ;	mov	edi, esi
  4198                              <1> ;	sub 	edi, 4
  4199                              <1> ;swpqs_3:
  4200                              <1> ;	dec	word [swpq_count]
  4201                              <1> ;	jz	short swpqs_5
  4202                              <1> ;swpqs_4:
  4203                              <1> ;	dec 	ecx
  4204                              <1> ;	rep	movsd	; shift up (to the head)
  4205                              <1> ;swpqs_5:
  4206                              <1> ;	xor	eax, eax
  4207                              <1> ;	mov	[edi], eax
  4208                              <1> ;swpqs_6:
  4209                              <1> ;	pop	ecx
  4210                              <1> ;	pop	esi
  4211                              <1> ;	pop	edi
  4212                              <1> ;swpqs_retn:
  4213                              <1> ;	retn		
  4214                              <1> ;swpqs_7:
  4215                              <1> ;	mov	edi, esi ; head
  4216                              <1> ;	lodsd
  4217                              <1> ;	; 20/07/2015
  4218                              <1> ;	mov	ebx, eax
  4219                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4220                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4221                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4222                              <1> ;		      ; ax = process number (1 to 4095)
  4223                              <1> ;	cmp	al, [u.uno]
  4224                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4225                              <1> ;	jne	short swpqs_8
  4226                              <1> ;	mov	eax, [u.pgdir]
  4227                              <1> ;	jmp	short swpqs_9
  4228                              <1> ;swpqs_8:
  4229                              <1> ;	; 09/06/2016
  4230                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4231                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4232                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4233                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4234                              <1> ;
  4235                              <1> ;	;shl	ax, 2
  4236                              <1> ;	shl	al, 2
  4237                              <1> ;	mov 	eax, [eax+p.upage-4]
  4238                              <1> ;	or	eax, eax
  4239                              <1> ;	jz	short swpqs_3 ; invalid upage
  4240                              <1> ;	add	eax, u.pgdir - user
  4241                              <1> ;			 ; u.pgdir value for the process
  4242                              <1> ;			 ; is in [eax]
  4243                              <1> ;	mov	eax, [eax]
  4244                              <1> ;	and	eax, eax
  4245                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4246                              <1> ;swpqs_9:
  4247                              <1> ;	push	edx
  4248                              <1> ;	; eax = page directory
  4249                              <1> ;	; ebx = virtual address
  4250                              <1> ;	call	get_pte
  4251                              <1> ;	mov	ebx, edx	; PTE address
  4252                              <1> ;	pop	edx
  4253                              <1> ;	; 10/06/2016
  4254                              <1> ;	jc	short swpqs_13 ; empty PDE
  4255                              <1> ;	; EAX = PTE value
  4256                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4257                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4258                              <1> ;			        ; from the queue (head)
  4259                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4260                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4261                              <1> ;			        ; from the queue (head) 	
  4262                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4263                              <1> ;	;jnz	short swpqs_11  ; present
  4264                              <1> ;			        ; accessed page
  4265                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4266                              <1> ;	jc	short swpqs_11  ; accessed page
  4267                              <1> ;
  4268                              <1> ;	dec	ecx
  4269                              <1> ;	mov	[swpq_count], cx
  4270                              <1> ;       jz      short swpqs_10
  4271                              <1> ;		; esi = head + 4
  4272                              <1> ;		; edi = head
  4273                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4274                              <1> ;swpqs_10:
  4275                              <1> ;	mov	[edi], ecx ; 0
  4276                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4277                              <1> ;
  4278                              <1> ;swpqs_11:
  4279                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4280                              <1> ;	; Rotation (head -> tail)
  4281                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4282                              <1> ;	jz	short swpqs_10
  4283                              <1> ;		; esi = head + 4
  4284                              <1> ;		; edi = head
  4285                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4286                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4287                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4288                              <1> ;
  4289                              <1> ;	mov	cx, [swpq_count]
  4290                              <1> ;
  4291                              <1> ;swpqs_12:
  4292                              <1> ;	mov	esi, swap_queue ; head
  4293                              <1> ;       jmp     swpqs_7
  4294                              <1> ;
  4295                              <1> ;swpqs_13:
  4296                              <1> ;	dec	ecx
  4297                              <1> ;	mov	[swpq_count], cx
  4298                              <1> ;       jz      swpqs_5
  4299                              <1> ;	jmp	short swpqs_12
  4300                              <1> 
  4301                              <1> ; 17/04/2021
  4302                              <1> ; ('add_to_swp_queue' procedure call is disabled as temporary)
  4303                              <1> 
  4304                              <1> ; 30/11/2021 - temporary !
  4305                              <1> ;add_to_swap_queue:
  4306                              <1> 	; 20/02/2017
  4307                              <1> 	; 20/07/2015
  4308                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4309                              <1> 	;
  4310                              <1> 	; Adds new page to swap queue
  4311                              <1> 	; (page directories and page tables must not be added
  4312                              <1> 	; to swap queue)	
  4313                              <1> 	;
  4314                              <1> 	; INPUT ->
  4315                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4316                              <1> 	;	[u.uno]
  4317                              <1> 	;	20/02/2017
  4318                              <1> 	;	(Linear address = CORE + user's virtual address)
  4319                              <1> 	;
  4320                              <1> 	; OUTPUT ->
  4321                              <1> 	;	EAX = [swpq_count]
  4322                              <1> 	;	      (after the PTE has been added)
  4323                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4324                              <1> 	;	      the PTE could not be added.
  4325                              <1> 	;
  4326                              <1> 	; Modified Registers -> EAX
  4327                              <1> 	;
  4328                              <1> ;	push	ebx
  4329                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4330                              <1> ;	mov	bl, [u.uno] ; current process number
  4331                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4332                              <1> ;				 ; it is already on the queue
  4333                              <1> ;		; then add it to the tail of the queue
  4334                              <1> ;	movzx	eax, word [swpq_count]
  4335                              <1> ;	cmp	ax, 1024
  4336                              <1> ;	jb	short atsq_1
  4337                              <1> ;	sub	ax, ax
  4338                              <1> ;	pop	ebx
  4339                              <1> ;	retn
  4340                              <1> ;atsq_1:
  4341                              <1> ;	push	esi
  4342                              <1> ;	mov	esi, swap_queue
  4343                              <1> ;	and	ax, ax
  4344                              <1> ;	jz	short atsq_2
  4345                              <1> ;	shl	ax, 2	; convert to offset
  4346                              <1> ;	add	esi, eax
  4347                              <1> ;	shr	ax, 2
  4348                              <1> ;atsq_2:
  4349                              <1> ;	inc	ax
  4350                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4351                              <1> ;	mov	[swpq_count], ax
  4352                              <1> ;	pop	esi
  4353                              <1> ;	pop	ebx
  4354                              <1> ;	retn
  4355                              <1> 
  4356                              <1> ; 17/04/2021
  4357                              <1> ; ('unlink_swap_block' procedure call is disabled as temporary)
  4358                              <1> 
  4359                              <1> ; 30/11/2021 - temporary !
  4360                              <1> ;unlink_swap_block:
  4361                              <1> 	; 15/09/2015
  4362                              <1> 	; 30/04/2015
  4363                              <1> 	; 18/04/2015
  4364                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4365                              <1> 	;
  4366                              <1> 	; INPUT -> 
  4367                              <1> 	;	EAX = swap disk/file offset address
  4368                              <1> 	;	      (bit 1 to bit 31)
  4369                              <1> 	; OUTPUT ->
  4370                              <1> 	;	[swpd_free] is increased
  4371                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4372                              <1> 	;
  4373                              <1> 	; Modified Registers -> EAX
  4374                              <1> 	;
  4375                              <1> ;	push	ebx
  4376                              <1> ;	push	edx
  4377                              <1> ;	;
  4378                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4379                              <1> ;				     ; 3 bits right
  4380                              <1> ;				     ; to get swap block/page number
  4381                              <1> ;	mov	edx, eax
  4382                              <1> ;	; 15/09/2015
  4383                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4384                              <1> ;				     ; (1 allocation bit = 1 page)
  4385                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4386                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4387                              <1> ;				     ; (to get 32 bit position)			
  4388                              <1> ;	;
  4389                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4390                              <1> ;	add	ebx, edx
  4391                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4392                              <1> ;				     ; (allocation bit position)	 
  4393                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4394                              <1> ;				     ; than the address in 'swpd_next' ?
  4395                              <1> ;				     ; (next/first free block value)		
  4396                              <1> ;	jnb	short uswpbl_1	     ; no	
  4397                              <1> ;	mov	[swpd_next], eax     ; yes	
  4398                              <1> ;uswpbl_1:
  4399                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4400                              <1> ;				     ; set relevant bit to 1.
  4401                              <1> ;				     ; set CF to the previous bit value	
  4402                              <1> ;	cmc			     ; complement carry flag	
  4403                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4404                              <1> ;				     ; if the block is already deallocated
  4405                              <1> ;				     ; before.	
  4406                              <1> ;       inc     dword [swpd_free]
  4407                              <1> ;uswpbl_2:
  4408                              <1> ;	pop	edx
  4409                              <1> ;	pop	ebx
  4410                              <1> ;	retn
  4411                              <1> 
  4412                              <1> ; 17/04/2021
  4413                              <1> ; ('link_swap_block' procedure call is disabled as temporary)
  4414                              <1> 
  4415                              <1> ; 30/11/2021 - temporary !
  4416                              <1> ;link_swap_block:
  4417                              <1> 	; 01/07/2015
  4418                              <1> 	; 18/04/2015
  4419                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4420                              <1> 	;
  4421                              <1> 	; INPUT -> none
  4422                              <1> 	;
  4423                              <1> 	; OUTPUT ->
  4424                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4425                              <1> 	;	      in sectors (corresponding 
  4426                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4427                              <1> 	;
  4428                              <1> 	;	CF = 1 and EAX = 0 
  4429                              <1> 	; 		   if there is not a free block to be allocated	
  4430                              <1> 	;
  4431                              <1> 	; Modified Registers -> none (except EAX)
  4432                              <1> 	;
  4433                              <1> 
  4434                              <1> ;	;mov	eax, [swpd_free]
  4435                              <1> ;	;and	eax, eax
  4436                              <1> ;	;jz	short out_of_swpspc
  4437                              <1> ;	;
  4438                              <1> ;	push	ebx
  4439                              <1> ;	push	ecx
  4440                              <1> ;	;
  4441                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4442                              <1> ;	mov	ecx, ebx
  4443                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4444                              <1> ;				 ; next_free_swap_block >> 5
  4445                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4446                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4447                              <1> ;lswbl_scan:
  4448                              <1> ;	cmp	ebx, ecx
  4449                              <1> ;	ja	short lswbl_notfound
  4450                              <1> ;	;
  4451                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4452                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4453                              <1> ;			   ; loads the destination with an index to
  4454                              <1> ;			   ; first set bit. (0 -> 31) 
  4455                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4456                              <1> ;	; 01/07/2015
  4457                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4458                              <1> ;			 ;
  4459                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4460                              <1> ;			 ;	  with value of 1 means 
  4461                              <1> ;			 ;	  the corresponding page is free 
  4462                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4463                              <1> ;	add	ebx, 4
  4464                              <1> ;			 ; We return back for searching next page block
  4465                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4466                              <1> ;			 ;	 we always will find at least 1 free block here.
  4467                              <1> ;	jmp    	short lswbl_scan
  4468                              <1> ;	;
  4469                              <1> ;lswbl_notfound:	
  4470                              <1> ;	sub	ecx, swap_alloc_table
  4471                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4472                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4473                              <1> ;	xor	eax, eax
  4474                              <1> ;	mov	[swpd_free], eax
  4475                              <1> ;	stc
  4476                              <1> ;lswbl_ok:
  4477                              <1> ;	pop	ecx
  4478                              <1> ;	pop	ebx
  4479                              <1> ;	retn
  4480                              <1> ;	;
  4481                              <1> ;;out_of_swpspc:
  4482                              <1> ;;	stc
  4483                              <1> ;;	retn
  4484                              <1> ;
  4485                              <1> ;lswbl_found:
  4486                              <1> ;	mov	ecx, ebx
  4487                              <1> ;	sub	ecx, swap_alloc_table
  4488                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4489                              <1> ;				 ; address/offset (to the next)
  4490                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4491                              <1> ;	;
  4492                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4493                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4494                              <1> ;				 ; in the destination.
  4495                              <1> ;				 ;
  4496                              <1> ;				 ; Reset the bit which is corresponding to the 
  4497                              <1> ;				 ; (just) allocated block.
  4498                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4499                              <1> ;	add	eax, ecx	 ; = block number
  4500                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4501                              <1> ;				 ; 1 block =  8 sectors
  4502                              <1> ;	;
  4503                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4504                              <1> ;	;
  4505                              <1> ;	; NOTE: The relevant page table entry will be updated
  4506                              <1> ;	;       according to this EAX value...
  4507                              <1> ;	;
  4508                              <1> ;	jmp	short lswbl_ok
  4509                              <1> 
  4510                              <1> ; 17/04/2021
  4511                              <1> ; ('logical_disk_read' procedure call is disabled as temporary)
  4512                              <1> 
  4513                              <1> ; 30/11/2021 - temporary !
  4514                              <1> ;logical_disk_read:
  4515                              <1> 	; 20/07/2015
  4516                              <1> 	; 09/03/2015 (temporary code here)
  4517                              <1> 	;
  4518                              <1> 	; INPUT ->
  4519                              <1> 	; 	ESI = Logical disk description table address
  4520                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4521                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4522                              <1> 	; 	ECX = Sector count
  4523                              <1> 	;
  4524                              <1> 	;
  4525                              <1> ;	retn
  4526                              <1> 
  4527                              <1> ; 17/04/2021
  4528                              <1> ; ('logical_disk_write' procedure call is disabled as temporary)
  4529                              <1> 
  4530                              <1> ; 30/11/2021 - temporary !
  4531                              <1> ;logical_disk_write:
  4532                              <1> 	; 20/07/2015
  4533                              <1> 	; 09/03/2015 (temporary code here)
  4534                              <1> 	;
  4535                              <1> 	; INPUT ->
  4536                              <1> 	; 	ESI = Logical disk description table address
  4537                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4538                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4539                              <1> 	; 	ECX = Sector count
  4540                              <1> 	;
  4541                              <1> ;	retn
  4542                              <1> 
  4543                              <1> get_physical_addr:
  4544                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  4545                              <1> 	;	(temporary modifications)
  4546                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4547                              <1> 	; 18/10/2015
  4548                              <1> 	; 29/07/2015
  4549                              <1> 	; 20/07/2015
  4550                              <1> 	; 04/06/2015
  4551                              <1> 	; 20/05/2015
  4552                              <1> 	; 28/04/2015
  4553                              <1> 	; 18/04/2015
  4554                              <1> 	; Get physical address
  4555                              <1> 	;     (allocates a new page for user if it is not present)
  4556                              <1> 	;	
  4557                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4558                              <1> 	; (buffer) address to physical address (of the buffer).)
  4559                              <1> 	; ('sys write', 'sys read' system calls...)
  4560                              <1> 	;
  4561                              <1> 	; INPUT ->
  4562                              <1> 	;	EBX = virtual address
  4563                              <1> 	;	u.pgdir = page directory (physical) address
  4564                              <1> 	;
  4565                              <1> 	; OUTPUT ->
  4566                              <1> 	;	EAX = physical address 
  4567                              <1> 	;	EBX = linear address	
  4568                              <1> 	;	EDX = physical address of the page frame
  4569                              <1> 	;	      (with attribute bits)
  4570                              <1> 	;	ECX = byte count within the page frame
  4571                              <1> 	;
  4572                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4573                              <1> 	;
  4574                              <1> 
  4575                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4576 000028D0 A1[C46D0000]        <1> 	mov	eax, [u.pgdir]
  4577                              <1> 
  4578                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4579                              <1> 	
  4580 000028D5 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4581                              <1> 	;
  4582                              <1> 	;mov	eax, [u.pgdir]
  4583 000028DB E816FDFFFF          <1> 	call	get_pte
  4584                              <1> 		; EDX = Page table entry address (if CF=0)
  4585                              <1> 	        ;       Page directory entry address (if CF=1)
  4586                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4587                              <1> 		; EAX = Page table entry value (page address)
  4588                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4589 000028E0 731C                <1> 	jnc	short gpa_1
  4590                              <1> 	;
  4591 000028E2 E8FDFBFFFF          <1> 	call	allocate_page
  4592 000028E7 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4593                              <1> gpa_0:
  4594 000028E9 E867FCFFFF          <1> 	call 	clear_page
  4595                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4596 000028EE 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4597                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4598                              <1> 			   ; (user, writable, present page)	
  4599 000028F0 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4600 000028F2 A1[C46D0000]        <1> 	mov	eax, [u.pgdir]	
  4601 000028F7 E8FAFCFFFF          <1> 	call	get_pte
  4602 000028FC 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4603                              <1> gpa_1:
  4604                              <1> 	; EAX = PTE value, EDX = PTE address
  4605 000028FE A801                <1> 	test 	al, PTE_A_PRESENT
  4606 00002900 750A                <1> 	jnz	short gpa_3
  4607 00002902 09C0                <1> 	or	eax, eax
  4608 00002904 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4609                              <1> 
  4610                              <1> ; 17/04/2021
  4611                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4612 00002906 EB2C                <1> 	jmp	short gpa_im_err  ; temporary !
  4613                              <1> 
  4614                              <1> 	; 20/07/2015
  4615                              <1> ;	push	ebp
  4616                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4617                              <1> ;	; reload swapped page
  4618                              <1> ;	call	reload_page ; 28/04/2015
  4619                              <1> ;	pop	ebp
  4620                              <1> ;	jc	short gpa_retn
  4621                              <1> gpa_2:
  4622                              <1> ; 17/04/2021
  4623                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  4624                              <1> 
  4625                              <1> 	; 20/07/2015
  4626                              <1> 	; 20/05/2015
  4627                              <1> 	; add this page to swap queue
  4628                              <1> ;	push	eax 
  4629                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4630                              <1> ;	call 	add_to_swap_queue
  4631                              <1> ;	pop	eax
  4632                              <1> 		; PTE address in EDX
  4633                              <1> 		; virtual address in EBX
  4634                              <1> 
  4635                              <1> 	; EAX = memory page address
  4636 00002908 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4637                              <1> 				  ; present flag, bit 0 = 1
  4638                              <1> 				  ; user flag, bit 2 = 1	
  4639                              <1> 				  ; writable flag, bit 1 = 1
  4640 0000290A 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4641                              <1> gpa_3:
  4642                              <1> 	; 18/10/2015
  4643 0000290C 89D9                <1> 	mov	ecx, ebx
  4644 0000290E 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4645 00002914 89C2                <1> 	mov 	edx, eax
  4646 00002916 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4647 0000291A 01C8                <1> 	add	eax, ecx
  4648 0000291C F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4649 0000291E 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4650 00002924 F8                  <1> 	clc
  4651                              <1> gpa_retn:
  4652 00002925 C3                  <1> 	retn	
  4653                              <1> gpa_4:	
  4654 00002926 E8B9FBFFFF          <1> 	call	allocate_page
  4655 0000292B 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4656 0000292D E823FCFFFF          <1> 	call	clear_page
  4657 00002932 EBD4                <1> 	jmp	short gpa_2
  4658                              <1> 
  4659                              <1> gpa_im_err:	
  4660 00002934 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4661                              <1> 				  ; Major error = 0 (No protection fault)	
  4662 00002939 C3                  <1> 	retn
  4663                              <1> 
  4664                              <1> ; 17/04/2021
  4665                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4666                              <1> 
  4667                              <1> ; 30/11/2021 - temporary !
  4668                              <1> ;reload_page:
  4669                              <1> 	; 20/07/2015
  4670                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4671                              <1> 	;
  4672                              <1> 	; Reload (Restore) swapped page at memory
  4673                              <1> 	;
  4674                              <1> 	; INPUT -> 
  4675                              <1> 	;	EBP = Virtual (linear) memory address
  4676                              <1> 	;	EAX = PTE value (swap disk sector address)
  4677                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4678                              <1> 	; OUTPUT ->
  4679                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4680                              <1> 	;
  4681                              <1> 	;	CF = 1 and EAX = error code
  4682                              <1> 	;
  4683                              <1> 	; Modified Registers -> none (except EAX)
  4684                              <1> 	;
  4685                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4686                              <1> ;	push	ebx      ;
  4687                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4688                              <1> ;	call	allocate_page
  4689                              <1> ;	jc	short rlp_im_err
  4690                              <1> ;	xchg 	eax, ebx	
  4691                              <1> ;	; EBX = Physical memory (page) address
  4692                              <1> ;	; EAX = Swap disk (offset) address
  4693                              <1> ;	; EBP = Virtual (linear) memory address
  4694                              <1> ;	call	swap_in
  4695                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4696                              <1> ;	mov	eax, ebx	
  4697                              <1> ;rlp_retn:
  4698                              <1> ;	pop	ebx
  4699                              <1> ;	retn
  4700                              <1> ;	
  4701                              <1> ;rlp_im_err:	
  4702                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4703                              <1> ;				  ; Major error = 0 (No protection fault)	
  4704                              <1> ;	jmp	short rlp_retn
  4705                              <1> ;
  4706                              <1> ;rlp_swp_err:
  4707                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4708                              <1> ;	jmp	short rlp_retn
  4709                              <1> 
  4710                              <1> copy_page_dir:
  4711                              <1> 	; 17/04/2021 (temporary modifications)
  4712                              <1> 	; 19/09/2015
  4713                              <1> 	; temporary - 07/09/2015
  4714                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4715                              <1> 	;
  4716                              <1> 	; INPUT -> 
  4717                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4718                              <1> 	;		    page directory.
  4719                              <1> 	; OUTPUT ->
  4720                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4721                              <1> 	;	       page directory.
  4722                              <1> 	;	(New page directory with new page table entries.)
  4723                              <1> 	;	(New page tables with read only copies of the parent's
  4724                              <1> 	;	pages.)
  4725                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4726                              <1> 	;
  4727                              <1> 	; Modified Registers -> none (except EAX)
  4728                              <1> 	;
  4729 0000293A E8A5FBFFFF          <1> 	call	allocate_page
  4730 0000293F 723E                <1> 	jc	short cpd_err
  4731                              <1> 	;
  4732 00002941 55                  <1> 	push	ebp ; 20/07/2015
  4733 00002942 56                  <1> 	push	esi
  4734 00002943 57                  <1> 	push	edi
  4735 00002944 53                  <1> 	push	ebx
  4736 00002945 51                  <1> 	push	ecx
  4737 00002946 8B35[C46D0000]      <1> 	mov	esi, [u.pgdir]
  4738 0000294C 89C7                <1> 	mov	edi, eax
  4739 0000294E 50                  <1> 	push	eax ; save child's page directory address
  4740                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4741                              <1> 	; (use same system space for all user page tables) 
  4742 0000294F A5                  <1> 	movsd
  4743 00002950 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4744 00002955 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4745                              <1> cpd_0:	
  4746 0000295A AD                  <1> 	lodsd
  4747                              <1> 	;or	eax, eax
  4748                              <1>         ;jnz	short cpd_1
  4749 0000295B A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4750 0000295D 7508                <1> 	jnz	short cpd_1
  4751                              <1>  	; (virtual address at the end of the page table)	
  4752 0000295F 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4753 00002965 EB0F                <1> 	jmp	short cpd_2
  4754                              <1> cpd_1:	
  4755 00002967 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4756 0000296B 89C3                <1> 	mov	ebx, eax
  4757                              <1> 	; EBX = Parent's page table address
  4758 0000296D E81F000000          <1> 	call	copy_page_table
  4759 00002972 720C                <1> 	jc	short cpd_p_err
  4760                              <1> 	; EAX = Child's page table address
  4761 00002974 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4762                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4763                              <1> 			 ; (present, writable, user)
  4764                              <1> cpd_2:
  4765 00002976 AB                  <1> 	stosd
  4766 00002977 E2E1                <1> 	loop	cpd_0
  4767                              <1> 	;
  4768 00002979 58                  <1> 	pop	eax  ; restore child's page directory address
  4769                              <1> cpd_3:
  4770 0000297A 59                  <1> 	pop	ecx
  4771 0000297B 5B                  <1> 	pop	ebx
  4772 0000297C 5F                  <1> 	pop	edi
  4773 0000297D 5E                  <1> 	pop	esi
  4774 0000297E 5D                  <1> 	pop	ebp
  4775                              <1> cpd_err:
  4776 0000297F C3                  <1> 	retn
  4777                              <1> cpd_p_err:
  4778                              <1> 	; release the allocated pages missing (recover free space)
  4779 00002980 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4780 00002981 8B1D[C46D0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4781 00002987 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4782 0000298C 29C0                <1> 	sub	eax, eax ; 0
  4783 0000298E F9                  <1> 	stc
  4784 0000298F EBE9                <1> 	jmp	short cpd_3	
  4785                              <1> 
  4786                              <1> copy_page_table:
  4787                              <1> 	; 17/04/2021 (temporary modifications)
  4788                              <1> 	; 19/09/2015
  4789                              <1> 	; temporary - 07/09/2015
  4790                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4791                              <1> 	;
  4792                              <1> 	; INPUT -> 
  4793                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4794                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4795                              <1> 	; OUTPUT ->
  4796                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4797                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4798                              <1> 	;	CF = 1 -> error 
  4799                              <1> 	;
  4800                              <1> 	; Modified Registers -> EBP (except EAX)
  4801                              <1> 	;
  4802 00002991 E84EFBFFFF          <1> 	call	allocate_page
  4803 00002996 7244                <1> 	jc	short cpt_err
  4804                              <1> 	;
  4805 00002998 50                  <1> 	push	eax ; *
  4806                              <1> 	;push 	ebx
  4807 00002999 56                  <1> 	push	esi
  4808 0000299A 57                  <1> 	push	edi
  4809 0000299B 52                  <1> 	push	edx
  4810 0000299C 51                  <1> 	push	ecx
  4811                              <1> 	;
  4812 0000299D 89DE                <1> 	mov	esi, ebx
  4813 0000299F 89C7                <1> 	mov	edi, eax
  4814 000029A1 89C2                <1> 	mov	edx, eax
  4815 000029A3 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4816                              <1> cpt_0:
  4817 000029A9 AD                  <1> 	lodsd
  4818 000029AA A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4819                              <1> 	;jnz	short cpt_1 (*)
  4820                              <1> 	; 17/04/2021 (temporary (*)
  4821                              <1> 	;and	eax, eax (*)
  4822 000029AC 741E                <1> 	jz	short cpt_2  ; 17/04/2021
  4823                              <1> 	
  4824                              <1> ; 17/04/2021
  4825                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4826                              <1> ;
  4827                              <1> ;	; ebp = virtual (linear) address of the memory page
  4828                              <1> ;	call	reload_page ; 28/04/2015
  4829                              <1> ;	jc	short cpt_p_err
  4830                              <1> cpt_1:
  4831 000029AE 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4832 000029B2 89C1                <1> 	mov	ecx, eax
  4833                              <1> 	; Allocate a new page for the child process
  4834 000029B4 E82BFBFFFF          <1> 	call	allocate_page
  4835 000029B9 721C                <1> 	jc	short cpt_p_err
  4836 000029BB 57                  <1> 	push	edi
  4837 000029BC 56                  <1> 	push	esi
  4838 000029BD 89CE                <1> 	mov	esi, ecx
  4839 000029BF 89C7                <1> 	mov	edi, eax
  4840 000029C1 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4841 000029C6 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4842 000029C8 5E                  <1> 	pop	esi
  4843 000029C9 5F                  <1> 	pop	edi
  4844                              <1> 	; 
  4845                              <1> ; 17/04/2021
  4846                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)	
  4847                              <1> ;
  4848                              <1> ;	push	ebx
  4849                              <1> ;	push	eax
  4850                              <1> ;	mov	ebx, ebp
  4851                              <1> ;	; ebx = virtual address of the memory page
  4852                              <1> ;	call	add_to_swap_queue
  4853                              <1> ;	pop	eax
  4854                              <1> ;	pop	ebx
  4855                              <1> 	;
  4856                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4857 000029CA 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4858                              <1> cpt_2:
  4859 000029CC AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4860                              <1> 	;
  4861 000029CD 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4862                              <1> 	;
  4863 000029D3 39D7                <1> 	cmp	edi, edx
  4864 000029D5 72D2                <1> 	jb	short cpt_0
  4865                              <1> cpt_p_err:
  4866 000029D7 59                  <1> 	pop	ecx
  4867 000029D8 5A                  <1> 	pop	edx
  4868 000029D9 5F                  <1> 	pop	edi
  4869 000029DA 5E                  <1> 	pop	esi
  4870                              <1> 	;pop	ebx
  4871 000029DB 58                  <1> 	pop	eax ; *
  4872                              <1> cpt_err:
  4873 000029DC C3                  <1> 	retn
  4874                              <1> 
  4875                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4876                              <1> 
  4877                              <1> ;; Data:
  4878                              <1> 
  4879                              <1> ; 09/03/2015
  4880                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4881                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4882                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  4883                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4884                              <1> ;swpd_next:  dd 0 ; next free page block
  4885                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2085                                  %include 'sysdefs.s' ; 09/03/2015
  2086                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2087                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2088                              <1> ; ****************************************************************************
  2089                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - SYSDEFS.INC
  2090                              <1> ; Last Modification: 12/06/2022
  2091                              <1> ;
  2092                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2093                              <1> ; (Modified from 
  2094                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2095                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2096                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2097                              <1> ; ----------------------------------------------------------------------------
  2098                              <1> ;
  2099                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2100                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2101                              <1> ; <Bell Laboratories (17/3/1972)>
  2102                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2103                              <1> ;
  2104                              <1> ; ****************************************************************************
  2105                              <1> 
  2106                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2107                              <1> ; (SB structure has been moved here from 'ux.s' 
  2108                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2109                              <1> ; (('ux.s' bss section addresses are being overlapped
  2110                              <1> ;    when SB structure is defined in 'ux.s'))
  2111                              <1> 
  2112                              <1> struc SB ; SuperBlock
  2113                              <1> 
  2114 00000000 ????????            <1> .Header:	resd 1
  2115                              <1> ;.HiddenSects:
  2116 00000004 ????????            <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2117                              <1> ;.TotalSects:
  2118 00000008 ????????            <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)
  2119 0000000C ????????            <1> .Version:	resd 1	
  2120 00000010 ????????            <1> .BlockSize:	resd 1	
  2121 00000014 ????????            <1> .InodeCount:	resd 1	
  2122 00000018 ????????            <1> .FreeMapAddr:	resd 1	
  2123 0000001C ????????            <1> .FreeMapSize:	resd 1	
  2124 00000020 ????????            <1> .InodeMapAddr:	resd 1	
  2125 00000024 ????????            <1> .InodeMapSize:	resd 1	
  2126 00000028 ????????            <1> .InodeTblAddr:	resd 1	
  2127 0000002C ????????            <1> .InodeTblSize:	resd 1	
  2128 00000030 ????????            <1> .FreeInodes:	resd 1	
  2129 00000034 ????????            <1> .FirstFreeIno:	resd 1	
  2130 00000038 ????????            <1> .FreeBlocks:	resd 1	
  2131 0000003C ????????            <1> .FirstFreeBlk:	resd 1	
  2132 00000040 <res 13h>           <1> .BootSecParms:	resb 19	; v1
  2133 00000053 ??????????          <1> .BSExtension:	resb 5	; v2 HDFS
  2134 00000058 ??                  <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2135 00000059 ??                  <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2136 0000005A ????                <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2137 0000005C ????????            <1> .ModifTime:	resd 1	; (last) modification time (*)
  2138 00000060 ????????            <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2139 00000064 ????????            <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2140 00000068 ??                  <1> .LBA_rw:	resb 1
  2141 00000069 ??                  <1> .ClusterSize:	resb 1
  2142 0000006A ??                  <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2143 0000006B ??                  <1> .Mounted:	resb 1
  2144 0000006C ????????            <1> .MountInode:	resd 1  ; double word
  2145 00000070 ??                  <1> .DevMajor:	resb 1
  2146 00000071 ??                  <1> .DevMinor:	resb 1
  2147 00000072 ??                  <1> .LongName:	resb 1
  2148 00000073 ??                  <1> .Direntry32:	resb 1
  2149                              <1> ; 18/07/2021
  2150 00000074 ????????            <1> .FileBuffer:	resd 1
  2151 00000078 ????????            <1> .ItabBuffer:	resd 1
  2152 0000007C ????????            <1> .ImapBuffer:	resd 1
  2153 00000080 ????????            <1> .FmapBuffer:	resd 1
  2154                              <1>  ; 15/07/2021
  2155 00000084 ????????            <1> .LastInode:	resd 1
  2156                              <1> ; 02/05/2021
  2157 00000088 ????????            <1> .FmapIndex:	resd 1
  2158 0000008C ????????            <1> .ImapIndex:	resd 1
  2159 00000090 ????????            <1> .ItableIndex:	resd 1
  2160 00000094 <res 168h>          <1> .Reserved:	resb 508-148 ; 18/07/2021
  2161 000001FC ????????            <1> .Footer:	resd 1
  2162                              <1> 
  2163                              <1> endstruc
  2164                              <1> 
  2165                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2166                              <1> ; (file structure has been moved here from 'ux.s' 
  2167                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2168                              <1> ; (('ux.s' bss section addresses are being overlapped
  2169                              <1> ;    when file structure is defined in 'ux.s'))
  2170                              <1> 
  2171                              <1> ; 22/11/2021
  2172                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  2173                              <1> 
  2174                              <1> struc file	; open files (fsp) structure
  2175 00000000 ????                <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  2176 00000002 ????                <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  2177 00000004 ??                  <1>   .drive:  resb 1  ; logical drive (disk) number
  2178 00000005 ??                  <1>   .flags:  resb 1  ; open mode and status
  2179 00000006 ??                  <1>   .count:  resb 1  ; number of processes that have file open
  2180                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  2181 00000007 ??                  <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  2182 00000008 ????????            <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  2183 0000000C ????????            <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  2184                              <1>  .size:  ; = 16		
  2185                              <1> endstruc 
  2186                              <1> 
  2187                              <1> nproc 	equ	16  ; number of processes
  2188                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2189                              <1> ;nbuf	equ	6   ; number of buffers (04/02/2016)
  2190                              <1> nbuf	equ	16  ; number of buffers ; 11/06/2022		
  2191                              <1> nfiles  equ	50  ; NFILES equ 50 ; 02/01/2022
  2192                              <1> 
  2193                              <1> ; 27/12/2021
  2194                              <1> ;NFILES	  equ   32  ; temporary ! ( 27/12/2021)
  2195                              <1> ; 02/01/2022
  2196                              <1> ;OPENFILES equ	10  ; open files (for user) ; 28/03/2020
  2197                              <1> 
  2198                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2199                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2200                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2201                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2202                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2203                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2204                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2205                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2206                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2207                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2208                              <1> 	; '/core' dump file size = 32768 bytes
  2209                              <1>  
  2210                              <1> ; 08/03/2014 
  2211                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)
  2212                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2213                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2214                              <1> 
  2215                              <1> ; 30/08/2013
  2216                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2217                              <1> 
  2218                              <1> ; 05/02/2014
  2219                              <1> ; process status
  2220                              <1> ;SFREE 	equ 0
  2221                              <1> ;SRUN	equ 1
  2222                              <1> ;SWAIT	equ 2
  2223                              <1> ;SZOMB	equ 3
  2224                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2225                              <1> 
  2226                              <1> ; 09/03/2015
  2227                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2228                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2229                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2230                              <1> 
  2231                              <1> ; 17/09/2015
  2232                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2233                              <1> 
  2234                              <1> ; 12/01/2022 (37,38,39)
  2235                              <1> ; 21/09/2015 (36) 
  2236                              <1> ; 01/07/2015 (35)
  2237                              <1> ; 14/07/2013 (0-34)
  2238                              <1> ; UNIX v1 system calls
  2239                              <1> _rele 	equ 0
  2240                              <1> _exit 	equ 1
  2241                              <1> _fork 	equ 2
  2242                              <1> _read 	equ 3
  2243                              <1> _write	equ 4
  2244                              <1> _open	equ 5
  2245                              <1> _close 	equ 6
  2246                              <1> _wait 	equ 7
  2247                              <1> _creat 	equ 8
  2248                              <1> _link 	equ 9
  2249                              <1> _unlink	equ 10
  2250                              <1> _exec	equ 11
  2251                              <1> _chdir	equ 12
  2252                              <1> _time 	equ 13
  2253                              <1> _mkdir 	equ 14
  2254                              <1> _chmod	equ 15
  2255                              <1> _chown	equ 16
  2256                              <1> _break	equ 17
  2257                              <1> _stat	equ 18
  2258                              <1> _seek	equ 19
  2259                              <1> _tell 	equ 20
  2260                              <1> _mount	equ 21
  2261                              <1> _umount	equ 22
  2262                              <1> _setuid	equ 23
  2263                              <1> _getuid	equ 24
  2264                              <1> _stime	equ 25
  2265                              <1> _quit	equ 26	
  2266                              <1> _intr	equ 27
  2267                              <1> _fstat	equ 28
  2268                              <1> _emt 	equ 29
  2269                              <1> _mdate 	equ 30
  2270                              <1> _stty 	equ 31
  2271                              <1> _gtty	equ 32
  2272                              <1> _ilgins	equ 33
  2273                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2274                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2275                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2276                              <1> ; 12/01/2022 - Retro UNIX 386 v1.2
  2277                              <1> ; Retro UNIX 386 v2 system calls
  2278                              <1> _setgid	equ 37
  2279                              <1> _getgid	equ 38
  2280                              <1> _sysver	equ 39 ; (get) Retro Unix 386 version
  2281                              <1> 
  2282                              <1> %macro sys 1-4
  2283                              <1>     ; 13/04/2015
  2284                              <1>     ; Retro UNIX 386 v1 system call.
  2285                              <1>     mov eax, %1
  2286                              <1>     %if %0 >= 2   
  2287                              <1>         mov ebx, %2
  2288                              <1>         %if %0 >= 3    
  2289                              <1>             mov ecx, %3
  2290                              <1>             %if %0 = 4
  2291                              <1>                mov edx, %4   
  2292                              <1>             %endif
  2293                              <1>         %endif
  2294                              <1>     %endif
  2295                              <1>     int 30h	   
  2296                              <1> %endmacro
  2297                              <1> 
  2298                              <1> ; 13/05/2015 - ERROR CODES
  2299                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2300                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2301                              <1> ; 14/05/2015
  2302                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2303                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2304                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2305                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error
  2306                              <1> ; 16/05/2015		
  2307                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2308                              <1> ; 18/05/2015
  2309                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2310                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2311                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2312                              <1> ; 07/06/2015
  2313                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2314                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2315                              <1> ; 09/06/2015
  2316                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2317                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2318                              <1> ; 16/06/2015
  2319                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2320                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2321                              <1> ; 22/06/2015
  2322                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2323                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2324                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2325                              <1> ; 23/06/2015
  2326                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2327                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2328                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2329                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2330                              <1> ; 27/06/2015
  2331                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2332                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2333                              <1> ; 29/06/2015
  2334                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error
  2335                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2336                              <1> ; 08/02/2022 
  2337                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2338                              <1> ; 10/10/2016
  2339                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2340                              <1> ; 18/05/2016
  2341                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2342                              <1> ; 15/10/2016
  2343                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2344                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2345                              <1> ; 16/10/2016
  2346                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2347                              <1> ; 08/02/2022
  2348                              <1> ERR_INV_FS	   equ 28 ;'invalid fs/superblock !' error
  2349                              <1> 
  2350                              <1> ; 12/06/2022
  2351                              <1> ; printer errors
  2352                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2353                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2354                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2355                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2356                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error
  2357                              <1> 
  2358                              <1> ; 26/08/2015
  2359                              <1> ; 24/07/2015
  2360                              <1> ; 24/06/2015
  2361                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2362                              <1> ; 01/07/2015
  2363                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2364                              <1> ;
  2365                              <1> ; 26/11/2021 ('no free blocks on disk !' error)
  2366                              <1> ERR_ALLOC	   equ 33  ; 'disk allocation error !'	
  2367                              <1> ; 22/11/2021
  2368                              <1> ERR_READ_ONLY_FS   equ 30  ; 'read only file system !' error
  2369                              <1> ; 28/11/2021
  2370                              <1> ERR_INV_FILE	   equ 255 ; 'invalid file (inode) !' error
  2371                              <1> ; 04/12/2021
  2372                              <1> ERR_PERM_DENIED	   equ 11  ; 'permission denied !' error
  2373                              <1> ; 11/12/2021
  2374                              <1> ERR_INV_FUNC	   equ 1   ; 'invalid system call !' error
  2375                              <1> ; 10/01/2022
  2376                              <1> ERR_INO_ALLOC	   equ 33  ; 'inode allocation error !'
  2377                              <1> ERR_NOT_REGULAR    equ 255 ; 'not regular file directory !' error
  2378                              <1> 
  2379                              <1> ; 12/01/2022 - Retro UNIX 386 v1.2
  2380                              <1> %define s.time systm+504 ; boot/sysinit time (or current time)
  2381                              <1> 		
  2086                                  %include 'u0.s'      ; 15/03/2015
  2087                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2088                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2089                              <1> ; ****************************************************************************
  2090                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.1) - SYS0.INC
  2091                              <1> ; Last Modification: 02/06/2022
  2092                              <1> ; ----------------------------------------------------------------------------
  2093                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2094                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2095                              <1> ;
  2096                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2097                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2098                              <1> ; <Bell Laboratories (17/3/1972)>
  2099                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2100                              <1> ;
  2101                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2102                              <1> ;
  2103                              <1> ; ****************************************************************************
  2104                              <1> 
  2105                              <1> sys_init:
  2106                              <1> 	; 23/02/2022
  2107                              <1> 	; 08/01/2022
  2108                              <1> 	; 01/01/2022
  2109                              <1> 	; 26/12/2021
  2110                              <1> 	; 27/11/2021
  2111                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification
  2112                              <1> 	; 18/10/2015
  2113                              <1> 	; 28/08/2015
  2114                              <1> 	; 24/08/2015
  2115                              <1> 	; 14/08/2015
  2116                              <1> 	; 24/07/2015 
  2117                              <1> 	; 02/07/2015
  2118                              <1> 	; 01/07/2015
  2119                              <1> 	; 23/06/2015
  2120                              <1> 	; 15/04/2015
  2121                              <1> 	; 13/04/2015
  2122                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2123                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2124                              <1> 	;
  2125                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2126                              <1> 	;
  2127                              <1> 	;; 14/02/2014
  2128                              <1> 	;; 14/07/2013
  2129                              <1> 	;mov	ax, 41
  2130                              <1> 	;mov	[rootdir], ax
  2131                              <1> 	;mov	[u.cdir], ax
  2132                              <1> 	;and	al, 1 ; 15/04/2015
  2133                              <1> 	
  2134                              <1> 	; 27/11/2021
  2135                              <1> 	; 18/04/2021 - Retro UNIX 386 v2
  2136 000029DD 31C0                <1> 	xor	eax, eax
  2137 000029DF FEC0                <1> 	inc	al	; eax = 1 (root directory inode) ; runix v2 fs
  2138 000029E1 A3[466D0000]        <1> 	mov	[rootdir], eax ; = 1 ; 28/10/2021 (32 bit)
  2139 000029E6 A3[686D0000]        <1> 	mov	[u.cdir], eax ; 28/10/2021 (32 bit)
  2140                              <1> 
  2141 000029EB A2[B56D0000]        <1> 	mov	[u.uno], al ; = 1
  2142                              <1> 	;mov	[mpid], ax ; 1 
  2143                              <1> 	;mov	[p.pid], ax ; 1
  2144                              <1> 	; 01/01/2022
  2145 000029F0 A2[446D0000]        <1> 	mov	[mpid], al
  2146 000029F5 A2[24690000]        <1> 	mov	[p.pid], al
  2147 000029FA A2[84690000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2148                              <1> 	;
  2149 000029FF B004                <1> 	mov	al, time_count ; 30/08/2013
  2150 00002A01 A2[AC6D0000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2151                              <1> 	; 02/07/2015
  2152 00002A06 A1[28680000]        <1> 	mov	eax, [k_page_dir]
  2153 00002A0B A3[C46D0000]        <1> 	mov	[u.pgdir], eax ; reset
  2154                              <1> 	; 18/10/2015
  2155                              <1> 	;sub	eax, eax
  2156                              <1> 	;mov	[u.ppgdir], eax ; 0
  2157                              <1>         ;
  2158                              <1>  	; 23/02/2022
  2159                              <1>  	;call	epoch
  2160                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2161                              <1> 	; 17/07/2013
  2162 00002A10 E884060000          <1> 	call 	bf_init ; buffer initialization
  2163                              <1> 	; 23/02/2022
  2164                              <1> 	; (save sysinit time on sb0)
  2165 00002A15 E829030000          <1> 	call	epoch
  2166 00002A1A A3[0C700000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2167                              <1> 	; 23/06/2015
  2168 00002A1F E8C0FAFFFF          <1> 	call	allocate_page
  2169                              <1> 	;;jc	error
  2170                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2171                              <1> 	; 05/12/2021
  2172 00002A24 7305                <1> 	jnc	short sysinit_1
  2173 00002A26 E989000000          <1> 	jmp	panic
  2174                              <1> sysinit_1:
  2175 00002A2B A3[C06D0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2176 00002A30 A3[94690000]        <1> 	mov	[p.upage], eax
  2177                              <1> 	;
  2178 00002A35 E81BFBFFFF          <1> 	call	clear_page
  2179                              <1> 	;
  2180                              <1> 	; 14/08/2015
  2181 00002A3A FA                  <1> 	cli
  2182                              <1> 	; 14/03/2015
  2183                              <1> 	; 17/01/2014
  2184 00002A3B E8D0010000          <1> 	call	sp_init ; serial port initialization
  2185                              <1> 	; 14/08/2015
  2186 00002A40 FB                  <1> 	sti
  2187                              <1> 	;
  2188                              <1> 	; 30/06/2015
  2189                              <1> 	;mov	esi, kernel_init_ok_msg
  2190                              <1> 	;call 	print_msg
  2191                              <1> 	;
  2192 00002A41 30DB                <1> 	xor	bl, bl ; video page 0
  2193                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2194 00002A43 E8C7330000          <1> 	call 	vp_clr  ; 17/07/2013
  2195 00002A48 FEC3                <1> 	inc	bl
  2196 00002A4A 80FB08              <1> 	cmp	bl, 8
  2197 00002A4D 72F4                <1> 	jb	short vp_clr_nxt
  2198                              <1> 	;
  2199                              <1> 	; 24/07/2015
  2200                              <1> 	;push	KDATA
  2201                              <1>         ;push	esp
  2202                              <1> 	;mov	[tss.esp0], esp
  2203                              <1>         ;mov	word [tss.ss0], KDATA
  2204                              <1> 	;
  2205                              <1> 	; 08/01/2022
  2206                              <1> 	; 24/08/2015
  2207                              <1> 	;; temporary (01/07/2015)
  2208                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2209                              <1> 	;		       ; it is not needed here !
  2210                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2211 00002A4F FE0D[586D0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2212                              <1> 			      ; 0 = executing a system call
  2213                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2214                              <1> 	;
  2215                              <1> 	;;; 06/08/2015
  2216                              <1> 	;;;call	getch ; wait for a key stroke
  2217                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2218                              <1> ;;sys_init_msg_wait:
  2219                              <1> ;;	push 	ecx
  2220                              <1> ;;	mov	al, 1
  2221                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2222                              <1> ;;	call	getc_n
  2223                              <1> ;;	pop	ecx
  2224                              <1> ;;	jnz	short sys_init_msg_ok
  2225                              <1> ;;	loop	sys_init_msg_wait
  2226                              <1> 	;
  2227                              <1> ;;sys_init_msg_ok:
  2228                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2229 00002A55 6A10                <1> 	push	KDATA ; ss
  2230 00002A57 54                  <1> 	push	esp
  2231 00002A58 9C                  <1> 	pushfd
  2232 00002A59 6A08                <1> 	push	KCODE ; cs
  2233 00002A5B 68[882A0000]        <1> 	push	init_exec ; eip
  2234 00002A60 8925[5C6D0000]      <1> 	mov	[u.sp], esp
  2235 00002A66 1E                  <1> 	push	ds
  2236 00002A67 06                  <1> 	push	es
  2237 00002A68 0FA0                <1> 	push	fs
  2238 00002A6A 0FA8                <1> 	push	gs	
  2239 00002A6C 60                  <1> 	pushad
  2240 00002A6D 8925[606D0000]      <1> 	mov	[u.usp], esp
  2241 00002A73 E80D1D0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2242                              <1> 		      ; and interrupt return components (for IRET)
  2243 00002A78 61                  <1> 	popad
  2244 00002A79 6658                <1> 	pop	ax ; gs
  2245 00002A7B 6658                <1> 	pop	ax ; fs
  2246 00002A7D 6658                <1> 	pop	ax ; es
  2247 00002A7F 6658                <1> 	pop	ax ; ds	
  2248 00002A81 58                  <1> 	pop	eax ; eip (init_exec)
  2249 00002A82 6658                <1> 	pop	ax ; cs (KCODE)
  2250 00002A84 58                  <1> 	pop	eax ; E-FLAGS
  2251 00002A85 58                  <1> 	pop	eax ; esp
  2252 00002A86 6658                <1> 	pop	ax ; ss (KDATA)
  2253                              <1> 	;
  2254                              <1> 	; 26/12/2021 ([u.ppgdir] is zero already)
  2255                              <1> 	;xor	eax, eax ; 0
  2256                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2257                              <1> 	;
  2258                              <1> 	; 02/07/2015
  2259                              <1> 	; [u.pgdir ] = [k_page_dir]
  2260                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2261                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2262                              <1> init_exec:
  2263                              <1> 	; 13/03/2013
  2264                              <1> 	; 24/07/2013
  2265 00002A88 BB[AA2A0000]        <1> 	mov	ebx, init_file
  2266 00002A8D B9[A22A0000]        <1> 	mov	ecx, init_argp
  2267                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2268                              <1> 	; ECX contains address of argument list pointer
  2269                              <1> 	;
  2270                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2271                              <1> 			      ; 0 = executing a system call
  2272                              <1> 	sys	_exec  ; execute file
  2283                              <2> 
  2284                              <2> 
  2285 00002A92 B80B000000          <2>  mov eax, %1
  2286                              <2>  %if %0 >= 2
  2287                              <2>  mov ebx, %2
  2288                              <2>  %if %0 >= 3
  2289                              <2>  mov ecx, %3
  2290                              <2>  %if %0 = 4
  2291                              <2>  mov edx, %4
  2292                              <2>  %endif
  2293                              <2>  %endif
  2294                              <2>  %endif
  2295 00002A97 CD30                <2>  int 30h
  2273 00002A99 7319                <1> 	jnc	short panic
  2274                              <1> 	;
  2275 00002A9B BE[40650000]        <1> 	mov	esi, etc_init_err_msg
  2276                              <1> 	; 22/11/2021
  2277                              <1> 	;call 	print_msg
  2278 00002AA0 EB17                <1> 	jmp	short key_to_reboot
  2279                              <1> 
  2280                              <1> ;align 4
  2281                              <1> init_argp:
  2282 00002AA2 [AA2A0000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2283                              <1> init_file:
  2284                              <1> 	; 24/08/2015
  2285 00002AAA 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2285 00002AB3 00                  <1>
  2286                              <1> panic:
  2287                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2288                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2289 00002AB4 BE[25650000]        <1> 	mov 	esi, panic_msg
  2290                              <1> key_to_reboot: ; 22/11/2021
  2291 00002AB9 E819000000          <1> 	call 	print_msg
  2292                              <1> ;key_to_reboot:
  2293                              <1> 	; 15/11/2015
  2294 00002ABE E89A310000          <1> 	call 	getch 
  2295                              <1> 		; wait for a character from the current tty
  2296                              <1> 	;
  2297 00002AC3 B00A                <1> 	mov	al, 0Ah
  2298 00002AC5 8A1D[56680000]      <1> 	mov	bl, [ptty] ; [active_page]
  2299 00002ACB B407                <1> 	mov	ah, 07h ; Black background, 
  2300                              <1> 			; light gray forecolor
  2301 00002ACD E8CFE8FFFF          <1> 	call 	write_tty
  2302 00002AD2 E96EE5FFFF          <1> 	jmp	cpu_reset 
  2303                              <1> 
  2304                              <1> print_msg:
  2305                              <1> 	; 01/07/2015
  2306                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2307                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2308                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2309                              <1> 	;
  2310                              <1> 	;
  2311 00002AD7 AC                  <1> 	lodsb
  2312                              <1> pmsg1:
  2313 00002AD8 56                  <1> 	push 	esi
  2314 00002AD9 0FB61D[56680000]    <1> 	movzx	ebx, byte [ptty]
  2315 00002AE0 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2316 00002AE2 E8BAE8FFFF          <1> 	call 	write_tty
  2317 00002AE7 5E                  <1> 	pop	esi
  2318 00002AE8 AC                  <1> 	lodsb
  2319 00002AE9 20C0                <1> 	and 	al, al
  2320 00002AEB 75EB                <1> 	jnz 	short pmsg1
  2321 00002AED C3                  <1> 	retn
  2322                              <1> 	
  2323                              <1> ctrlbrk:
  2324                              <1> 	; 06/02/2022
  2325                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2326                              <1> 	; 12/11/2015
  2327                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2328                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2329                              <1> 	;
  2330                              <1> 	; INT 1Bh (control+break) handler		
  2331                              <1> 	;
  2332                              <1>       	; Retro Unix 8086 v1 feature only!
  2333                              <1>       	;
  2334 00002AEE 66833D[B06D0000]00  <1> 	cmp 	word [u.intr], 0
  2335 00002AF6 764B                <1> 	jna 	short cbrk4
  2336                              <1> cbrk0:
  2337                              <1> 	; 12/11/2015
  2338                              <1> 	; 06/12/2013
  2339 00002AF8 66833D[B26D0000]00  <1> 	cmp 	word [u.quit], 0
  2340 00002B00 7441                <1> 	jz	short cbrk4
  2341                              <1> 	;
  2342                              <1> 	; 20/09/2013	
  2343                              <1> 	;push 	ax
  2344                              <1> 	; 04/12/2021
  2345 00002B02 50                  <1> 	push	eax
  2346                              <1> 
  2347                              <1> 	; 06/02/2022
  2348                              <1> 	; (repetitive ctrl+brk check) 
  2349 00002B03 66A1[B26D0000]      <1> 	mov	ax, [u.quit]
  2350 00002B09 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2351 00002B0B 7435                <1> 	jz	short cbrk3
  2352                              <1> 
  2353                              <1> 	; 06/12/2013
  2354 00002B0D A0[56680000]        <1> 	mov	al, [ptty]
  2355                              <1> 	;
  2356                              <1> 	; 12/11/2015
  2357                              <1> 	;
  2358                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2359                              <1> 	; or ctrl+break from console (pseudo) tty
  2360                              <1> 	; (!redirection!)
  2361                              <1> 	;
  2362 00002B12 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2363 00002B14 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2364                              <1> 	;	
  2365                              <1> 	; Serial port interrupt handler sets [ptty]
  2366                              <1> 	; to the port's tty number (as temporary).
  2367                              <1> 	;
  2368                              <1> 	; If active process is using a stdin or 
  2369                              <1> 	; stdout redirection (by the shell),
  2370                              <1>         ; console tty keyboard must be available
  2371                              <1> 	; to terminate running process,
  2372                              <1> 	; in order to prevent a deadlock. 
  2373                              <1> 	;
  2374 00002B16 52                  <1> 	push	edx
  2375 00002B17 0FB615[B56D0000]    <1> 	movzx	edx, byte [u.uno]
  2376 00002B1E 3A82[63690000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2377 00002B24 5A                  <1> 	pop	edx
  2378 00002B25 7412                <1> 	je	short cbrk2
  2379                              <1> cbrk1:
  2380 00002B27 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2381                              <1> 	; 06/12/2013
  2382 00002B29 3A05[9A6D0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2383 00002B2F 7408                <1> 	je	short cbrk2	
  2384 00002B31 3A05[9B6D0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2385 00002B37 7509                <1> 	jne	short cbrk3	
  2386                              <1> cbrk2:
  2387                              <1> 	;; 06/12/2013
  2388                              <1> 	;mov	ax, [u.quit]
  2389                              <1> 	;and	ax, ax
  2390                              <1> 	;jz	short cbrk3
  2391                              <1> 	;
  2392                              <1> 	;xor	ax, ax ; 0
  2393                              <1> 	;dec	ax
  2394                              <1> 	; 04/12/2021
  2395 00002B39 31C0                <1> 	xor	eax, eax ; 0
  2396 00002B3B 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2397                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2398 00002B3C 66A3[B26D0000]      <1> 	mov	[u.quit], ax
  2399                              <1> cbrk3:
  2400                              <1> 	;pop	ax
  2401                              <1> 	; 04/12/2021
  2402 00002B42 58                  <1> 	pop	eax
  2403                              <1> cbrk4:
  2404 00002B43 C3                  <1> 	retn
  2405                              <1> 
  2406                              <1> com2_int:
  2407                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2408                              <1> 	; 07/11/2015 
  2409                              <1> 	; 24/10/2015
  2410                              <1> 	; 23/10/2015
  2411                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2412                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2413                              <1> 	; < serial port 2 interrupt handler >
  2414                              <1> 	;
  2415 00002B44 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2416                              <1> 	;;push	eax
  2417                              <1> 	; 08/01/2022
  2418 00002B47 29C0                <1> 	sub	eax, eax
  2419 00002B49 B009                <1> 	mov	al, 9
  2420                              <1> 	;mov	ax, 9
  2421 00002B4B EB07                <1> 	jmp	short comm_int
  2422                              <1> com1_int:
  2423                              <1> 	; 07/11/2015
  2424                              <1> 	; 24/10/2015
  2425 00002B4D 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2426                              <1> 	; 23/10/2015
  2427                              <1> 	;push	eax
  2428                              <1> 	; 08/01/2022
  2429 00002B50 29C0                <1> 	sub	eax, eax
  2430 00002B52 B008                <1> 	mov	al, 8
  2431                              <1> 	;mov	ax, 8
  2432                              <1> comm_int:
  2433                              <1> 	; 08/01/2022
  2434                              <1> 	; 20/11/2015
  2435                              <1> 	; 18/11/2015
  2436                              <1> 	; 17/11/2015
  2437                              <1> 	; 16/11/2015
  2438                              <1> 	; 09/11/2015
  2439                              <1> 	; 08/11/2015
  2440                              <1> 	; 07/11/2015
  2441                              <1> 	; 06/11/2015 (serial4.asm, 'serial')	
  2442                              <1> 	; 01/11/2015
  2443                              <1> 	; 26/10/2015
  2444                              <1> 	; 23/10/2015
  2445 00002B54 53                  <1> 	push	ebx
  2446 00002B55 56                  <1> 	push	esi
  2447 00002B56 57                  <1> 	push	edi
  2448 00002B57 1E                  <1> 	push 	ds
  2449 00002B58 06                  <1> 	push 	es
  2450                              <1> 	; 18/11/2015
  2451 00002B59 0F20DB              <1> 	mov	ebx, cr3
  2452 00002B5C 53                  <1> 	push	ebx ; ****
  2453                              <1> 	;
  2454 00002B5D 51                  <1> 	push	ecx ; ***
  2455 00002B5E 52                  <1> 	push	edx ; **
  2456                              <1> 	;
  2457 00002B5F BB10000000          <1> 	mov	ebx, KDATA
  2458 00002B64 8EDB                <1> 	mov	ds, bx
  2459 00002B66 8EC3                <1> 	mov	es, bx
  2460                              <1> 	;
  2461 00002B68 8B0D[28680000]      <1> 	mov	ecx, [k_page_dir]
  2462 00002B6E 0F22D9              <1> 	mov	cr3, ecx
  2463                              <1> 	; 20/11/2015
  2464                              <1> 	; Interrupt identification register
  2465 00002B71 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2466                              <1> 	;
  2467 00002B75 3C08                <1> 	cmp 	al, 8 
  2468 00002B77 7702                <1> 	ja 	short com_i0
  2469                              <1> 	;
  2470                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2471                              <1> 	; 20/11/2015
  2472                              <1> 	; 17/11/2015
  2473                              <1> 	; 16/11/2015
  2474                              <1> 	; 15/11/2015
  2475                              <1> 	; 24/10/2015
  2476                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2477                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2478                              <1> 	; < serial port 1 interrupt handler >
  2479                              <1> 	;
  2480 00002B79 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2481                              <1> com_i0:
  2482                              <1> 	;push	eax ; *
  2483                              <1> 	; 07/11/2015
  2484 00002B7B A2[96680000]        <1> 	mov 	byte [ccomport], al
  2485                              <1> 	; 09/11/2015
  2486                              <1> 	;movzx	ebx, ax ; 8 or 9
  2487                              <1> 	; 08/01/2022
  2488 00002B80 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2489                              <1> 	; 17/11/2015
  2490                              <1>  	; reset request for response status
  2491 00002B82 88A3[8C680000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2492                              <1> 	;
  2493                              <1> 	; 20/11/2015
  2494 00002B88 EC                  <1> 	in	al, dx		; read interrupt id. register
  2495 00002B89 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2496 00002B8B 2404                <1> 	and	al, 4		; received data available?	
  2497 00002B8D 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2498                              <1> 	;
  2499                              <1> 	; 20/11/2015
  2500 00002B8F 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2501 00002B92 EC                  <1> 	in	al, dx     	; read character
  2502                              <1> 	;JMP	$+2	   	; I/O DELAY
  2503                              <1> 	; 08/11/2015
  2504                              <1> 	; 07/11/2015
  2505 00002B93 89DE                <1> 	mov	esi, ebx 
  2506 00002B95 89DF                <1> 	mov	edi, ebx
  2507 00002B97 81C6[90680000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2508 00002B9D 81C7[92680000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2509 00002BA3 8806                <1> 	mov	[esi], al ; received char (current char)
  2510                              <1> 	; query
  2511 00002BA5 20C0                <1> 	and	al, al
  2512 00002BA7 7527                <1> 	jnz	short com_i2
  2513                              <1>    	; response
  2514                              <1> 	; 17/11/2015
  2515                              <1> 	; set request for response status
  2516 00002BA9 FE83[8C680000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2517                              <1> 	;
  2518 00002BAF 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2519 00002BB3 EC                  <1> 	in	al, dx	   	; read line status register 
  2520 00002BB4 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2521 00002BB6 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2522 00002BB8 7445                <1> 	jz	short com_eoi 	; no
  2523 00002BBA B0FF                <1> 	mov 	al, 0FFh   	; response			
  2524 00002BBC 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2525 00002BC0 EE                  <1> 	out	dx, al	   	; send on serial port
  2526                              <1> 	; 17/11/2015
  2527 00002BC1 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2528 00002BC4 7502                <1> 	jne 	short com_i1    ; no
  2529 00002BC6 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2530                              <1> com_i1:
  2531                              <1> 	; 17/11/2015
  2532                              <1> 	; reset request for response status (again)
  2533 00002BC8 FE8B[8C680000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2534 00002BCE EB2F                <1> 	jmp	short com_eoi
  2535                              <1> com_i2:	
  2536                              <1> 	; 08/11/2015
  2537 00002BD0 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2538 00002BD2 7417                <1> 	je	short com_i3	; (check for response signal)
  2539                              <1> 	; 07/11/2015
  2540 00002BD4 3C04                <1> 	cmp	al, 04h	; EOT
  2541 00002BD6 751C                <1> 	jne	short com_i4	
  2542                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2543                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2544                              <1> 	; 08/11/2015
  2545                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2546 00002BD8 861D[56680000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2547 00002BDE E80BFFFFFF          <1> 	call 	ctrlbrk
  2548 00002BE3 861D[56680000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2549                              <1> 	;mov	al, 04h ; EOT
  2550                              <1> 	; 08/11/2015
  2551 00002BE9 EB09                <1> 	jmp	short com_i4	
  2552                              <1> com_i3:
  2553                              <1> 	; 08/11/2015
  2554                              <1> 	; If 0FFh has been received just after a query
  2555                              <1> 	; (schar, ZERO), it is a response signal.
  2556                              <1> 	; 17/11/2015
  2557 00002BEB 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2558 00002BEE 7704                <1> 	ja	short com_i4 ; no
  2559                              <1> 	; reset query status (schar)
  2560 00002BF0 8807                <1> 	mov	[edi], al ; 0FFh
  2561 00002BF2 FEC0                <1> 	inc	al ; 0
  2562                              <1> com_i4:
  2563                              <1> 	; 27/07/2014
  2564                              <1> 	; 09/07/2014
  2565 00002BF4 D0E3                <1> 	shl	bl, 1	
  2566 00002BF6 81C3[58680000]      <1> 	add	ebx, ttychr
  2567                              <1> 	; 23/07/2014 (always overwrite)
  2568                              <1> 	;;cmp	word [ebx], 0
  2569                              <1> 	;;ja	short com_eoi
  2570                              <1> 	;
  2571 00002BFC 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2572                              <1> 			    ; scan code = 0
  2573                              <1> com_eoi:
  2574                              <1> 	;mov	al, 20h
  2575                              <1> 	;out	20h, al	   ; end of interrupt
  2576                              <1> 	;
  2577                              <1> 	; 07/11/2015
  2578                              <1>       	;pop	eax ; *
  2579 00002BFF A0[96680000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2580                              <1> 	; al = tty number (8 or 9)
  2581 00002C04 E8561C0000          <1>         call	wakeup
  2582                              <1> com_iret:
  2583                              <1> 	; 23/10/2015
  2584 00002C09 5A                  <1> 	pop	edx ; **
  2585 00002C0A 59                  <1> 	pop	ecx ; ***
  2586                              <1> 	; 18/11/2015
  2587                              <1> 	;pop	eax ; ****
  2588                              <1> 	;mov	cr3, eax
  2589                              <1> 	;jmp	iiret
  2590 00002C0B E973DDFFFF          <1> 	jmp	iiretp
  2591                              <1> 
  2592                              <1> ;iiretp: ; 01/09/2015
  2593                              <1> ;	; 28/08/2015
  2594                              <1> ;	pop	eax ; (*) page directory
  2595                              <1> ;	mov	cr3, eax
  2596                              <1> ;iiret:
  2597                              <1> ;	; 22/08/2014
  2598                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2599                              <1> ;	out	20h, al	; 8259 PORT
  2600                              <1> ;	;
  2601                              <1> ;	pop	es
  2602                              <1> ;	pop	ds
  2603                              <1> ;	pop	edi
  2604                              <1> ;	pop	esi
  2605                              <1> ;	pop	ebx ; 29/08/2014
  2606                              <1> ;	pop 	eax
  2607                              <1> ;	iretd
  2608                              <1> 
  2609                              <1> sp_init:
  2610                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2611                              <1> 	; 07/11/2015
  2612                              <1> 	; 29/10/2015
  2613                              <1> 	; 26/10/2015
  2614                              <1> 	; 23/10/2015
  2615                              <1> 	; 29/06/2015
  2616                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2617                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2618                              <1> 	; Initialization of Serial Port Communication Parameters
  2619                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2620                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2621                              <1> 	;
  2622                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2623                              <1> 	;
  2624                              <1> 	; INPUT:  (29/06/2015)
  2625                              <1> 	;	AL = 0 for COM1
  2626                              <1> 	;	     1 for COM2
  2627                              <1> 	;	AH = Communication parameters	
  2628                              <1> 	;
  2629                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2630                              <1> 	;	Bit	4	3	2	1	0
  2631                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2632                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2633                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2634                              <1> 	;		11 = even
  2635                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2636                              <1> 	;		Retro UNIX 386 v1 feature only !
  2637                              <1> 	;	Bit	7    6    5  | Baud rate
  2638                              <1> 	;		------------------------
  2639                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2640                              <1> 	;		0    0    1  | 9600 (12)
  2641                              <1> 	;		0    1    0  | 19200 (6) 
  2642                              <1> 	;		0    1	  1  | 38400 (3) 
  2643                              <1> 	;		1    0	  0  | 14400 (8)
  2644                              <1> 	;		1    0	  1  | 28800 (4)
  2645                              <1> 	;		1    1    0  | 57600 (2)
  2646                              <1> 	;		1    1    1  | 115200 (1) 	
  2647                              <1> 	
  2648                              <1> 	; References:	
  2649                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2650                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2651                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2652                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2653                              <1> 	;
  2654                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2655                              <1> 	;
  2656 00002C10 BB[92680000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2657 00002C15 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2658                              <1> 	; 29/10/2015
  2659 00002C19 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2660 00002C1D E84F000000          <1> 	call	sp_i3	; call A4	
  2661 00002C22 A880                <1> 	test	al, 80h
  2662 00002C24 740E                <1> 	jz	short sp_i0 ; OK..
  2663                              <1> 		; Error !
  2664                              <1> 	;mov	dx, 3F8h
  2665 00002C26 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2666                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2667                              <1> 	; 08/01/2022
  2668 00002C29 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2669 00002C2B E841000000          <1> 	call	sp_i3	; call A4	
  2670 00002C30 A880                <1> 	test	al, 80h
  2671 00002C32 7508                <1> 	jnz	short sp_i1
  2672                              <1> sp_i0:
  2673                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2674                              <1>         ; (INT 14h initialization code disables interrupts.)
  2675                              <1> 	;
  2676 00002C34 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2677 00002C37 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2678                              <1> sp_i1:
  2679 00002C3C 43                  <1> 	inc	ebx
  2680 00002C3D 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2681                              <1> 	; 29/10/2015
  2682                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2683                              <1> 	; 08/01/2022
  2684 00002C41 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2685 00002C43 E829000000          <1> 	call	sp_i3	; call A4	
  2686 00002C48 A880                <1> 	test	al, 80h
  2687 00002C4A 740E                <1> 	jz	short sp_i2 ; OK..
  2688                              <1> 		; Error !
  2689                              <1> 	;mov	dx, 2F8h
  2690 00002C4C 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2691                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2692                              <1> 	; 08/01/2022
  2693 00002C4F B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2694 00002C51 E81B000000          <1> 	call	sp_i3	; call A4	
  2695 00002C56 A880                <1> 	test	al, 80h
  2696 00002C58 7516                <1> 	jnz	short sp_i7
  2697                              <1> sp_i2:
  2698 00002C5A C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2699                              <1> sp_i6:
  2700                              <1> 	;; COM2 - enabling IRQ 3
  2701                              <1> 	; 08/01/2022
  2702 00002C5D B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2703                              <1> 	; 07/11/2015
  2704                              <1> 	; 26/10/2015
  2705                              <1> 	;pushf
  2706                              <1> 	;cli
  2707                              <1> 	;;
  2708                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2709                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2710                              <1> 	;in	al, dx 	   		; read register
  2711                              <1> 	;JMP	$+2	   		; I/O DELAY
  2712                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2713                              <1> 	;out	dx, al     		; write back to register
  2714                              <1> 	;JMP	$+2	   		; I/O DELAY
  2715                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2716                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2717                              <1> 	;in	al, dx     		; read register
  2718                              <1> 	;JMP	$+2	   		; I/O DELAY
  2719                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2720                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2721                              <1> 	;out	dx, al 	   		; write back to register
  2722                              <1> 	;JMP	$+2        		; I/O DELAY
  2723                              <1> 	;in	al, 21h    		; read interrupt mask register
  2724                              <1> 	;JMP	$+2	   		; I/O DELAY
  2725                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2726                              <1> 	;out	21h, al    		; write back to register
  2727                              <1> 	;
  2728                              <1> 	; 08/01/2022
  2729 00002C5F 9C                  <1> 	pushf
  2730 00002C60 E8AA000000          <1> 	call	sp_i8
  2731                              <1> 	; 23/10/2015
  2732 00002C65 B8[442B0000]        <1> 	mov 	eax, com2_int
  2733 00002C6A A3[64310000]        <1> 	mov	[com2_irq3], eax
  2734                              <1> 	; 26/10/2015
  2735 00002C6F 9D                  <1> 	popf	
  2736                              <1> sp_i7:
  2737 00002C70 C3                  <1> 	retn
  2738                              <1> 
  2739                              <1> sp_i3:
  2740                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2741                              <1> 	; 28/10/2015
  2742 00002C71 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2743 00002C73 B000                <1> 	mov	al, 0
  2744 00002C75 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2745 00002C76 EB00                <1> 	JMP	$+2			; I/O DELAY
  2746 00002C78 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2747 00002C7B B080                <1> 	mov	al, 80h			
  2748 00002C7D EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2749                              <1> 	;-----	SET BAUD RATE DIVISOR
  2750                              <1> 	; 26/10/2015
  2751 00002C7E 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2752                              <1> 					; of the divisor value
  2753 00002C81 88C8                <1> 	mov	al, cl	; 1
  2754 00002C83 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2755                              <1> 					; 2 = 57600 baud
  2756                              <1> 					; 3 = 38400 baud
  2757                              <1> 					; 6 = 19200 baud
  2758                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2759 00002C84 EB00                <1> 	JMP	$+2			; I/O DELAY
  2760 00002C86 28C0                <1> 	sub	al, al
  2761 00002C88 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2762                              <1> 					; of the divisor value
  2763 00002C8A EE                  <1> 	out	dx, al ; 0
  2764 00002C8B EB00                <1> 	JMP	$+2			; I/O DELAY
  2765                              <1> 	;	
  2766 00002C8D 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2767                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2768 00002C8F 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2769 00002C92 EE                  <1> 	out	dx, al			
  2770 00002C93 EB00                <1> 	JMP	$+2			; I/O DELAY
  2771                              <1> 	; 29/10/2015
  2772 00002C95 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2773 00002C97 30C0                <1> 	xor	al, al			; 0
  2774 00002C99 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2775 00002C9A EB00                <1> 	JMP	$+2	
  2776                              <1> sp_i4:
  2777                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2778                              <1> 	; 29/06/2015 (line status after modem status)
  2779 00002C9C 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2780                              <1> sp_i4s:
  2781 00002C9F EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2782 00002CA0 EB00                <1> 	JMP	$+2			; I/O DELAY
  2783 00002CA2 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2784 00002CA4 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2785                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2786 00002CA6 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2787                              <1> 	; AL = Line status, AH = Modem status
  2788 00002CA7 C3                  <1> 	retn
  2789                              <1> 
  2790                              <1> sp_status:
  2791                              <1> 	; 29/06/2015
  2792                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2793                              <1> 	; Get serial port status
  2794 00002CA8 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2795 00002CAC 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2796                              <1> 					; dx = 2FEh for COM2
  2797 00002CAE EBEF                <1> 	jmp	short sp_i4s
  2798                              <1> 
  2799                              <1> sp_setp: ; Set serial port communication parameters
  2800                              <1> 	; 08/01/2022
  2801                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2802                              <1> 	; 07/11/2015
  2803                              <1> 	; 29/10/2015
  2804                              <1> 	; 29/06/2015
  2805                              <1> 	; Retro UNIX 386 v1 feature only !	
  2806                              <1> 	;
  2807                              <1> 	; INPUT:
  2808                              <1> 	;	AL = 0 for COM1
  2809                              <1> 	;	     1 for COM2
  2810                              <1> 	;	AH = Communication parameters (*)
  2811                              <1> 	; OUTPUT:
  2812                              <1> 	;	CL = Line status
  2813                              <1> 	;	CH = Modem status
  2814                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2815                              <1> 	;		 'invalid parameter !' 
  2816                              <1> 	;		 	 or
  2817                              <1> 	;		 'device not ready !' error
  2818                              <1> 	;	
  2819                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2820                              <1> 	;	Bit	4	3	2	1	0
  2821                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2822                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2823                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2824                              <1> 	;		11 = even
  2825                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2826                              <1> 	;		Retro UNIX 386 v1 feature only !
  2827                              <1> 	;	Bit	7    6    5  | Baud rate
  2828                              <1> 	;		------------------------
  2829                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2830                              <1> 	;		0    0    1  | 9600 (12)
  2831                              <1> 	;		0    1    0  | 19200 (6) 
  2832                              <1> 	;		0    1	  1  | 38400 (3) 
  2833                              <1> 	;		1    0	  0  | 14400 (8)
  2834                              <1> 	;		1    0	  1  | 28800 (4)
  2835                              <1> 	;		1    1    0  | 57600 (2)
  2836                              <1> 	;		1    1    1  | 115200 (1) 
  2837                              <1> 	;
  2838                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2839                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2840                              <1> 	;
  2841                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2842                              <1> 	;
  2843 00002CB0 66BAF803            <1> 	mov	dx, 3F8h
  2844 00002CB4 BB[92680000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2845 00002CB9 3C01                <1> 	cmp	al, 1
  2846 00002CBB 7770                <1> 	ja 	short sp_invp_err
  2847 00002CBD 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2848 00002CBF FECE                <1> 	dec	dh ; 2F8h
  2849 00002CC1 43                  <1> 	inc	ebx ; COM2 control byte offset
  2850                              <1> sp_setp1:
  2851                              <1> 	; 29/10/2015
  2852 00002CC2 8823                <1> 	mov	[ebx], ah
  2853 00002CC4 0FB6CC              <1> 	movzx 	ecx, ah
  2854 00002CC7 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2855 00002CCA 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2856 00002CCD 8A81[3C2D0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2857 00002CD3 6689C1              <1> 	mov	cx, ax
  2858 00002CD6 E896FFFFFF          <1> 	call	sp_i3
  2859 00002CDB 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2860 00002CDE A880                <1> 	test	al, 80h
  2861 00002CE0 740F                <1> 	jz	short sp_setp2
  2862 00002CE2 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2863                              <1> stp_dnr_err:
  2864 00002CE5 C705[D86D0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2864 00002CED 0000                <1>
  2865                              <1> 	; CL = Line status, CH = Modem status
  2866 00002CEF F9                  <1> 	stc
  2867 00002CF0 C3                  <1> 	retn
  2868                              <1> sp_setp2:
  2869 00002CF1 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2870                              <1>         ;jna	sp_i6
  2871                              <1> 		      ; COM1 (3F?h)
  2872                              <1> 	; 24/12/2021
  2873 00002CF4 7705                <1> 	ja	short sp_i5
  2874 00002CF6 E962FFFFFF          <1> 	jmp	sp_i6
  2875                              <1> sp_i5: 
  2876                              <1> 	; 08/01/2022
  2877 00002CFB B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2878                              <1> 	; 07/11/2015
  2879                              <1> 	; 26/10/2015
  2880                              <1> 	; 29/06/2015
  2881                              <1> 	;
  2882                              <1> 	;; COM1 - enabling IRQ 4
  2883                              <1> 	;pushf
  2884                              <1> 	;cli
  2885                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2886                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2887                              <1> 	;in	al, dx 	   		; read register
  2888                              <1> 	;JMP	$+2			; I/O DELAY
  2889                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2890                              <1> 	;out	dx, al     		; write back to register
  2891                              <1> 	;JMP	$+2			; I/O DELAY
  2892                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2893                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2894                              <1> 	;in	al, dx     		; read register
  2895                              <1> 	;JMP	$+2			; I/O DELAY
  2896                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2897                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2898                              <1> 	;out	dx, al 	   		; write back to register
  2899                              <1> 	;JMP	$+2        		; I/O DELAY
  2900                              <1> 	;in	al, 21h    		; read interrupt mask register
  2901                              <1> 	;JMP	$+2			; I/O DELAY
  2902                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2903                              <1> 	;out	21h, al    		; write back to register
  2904                              <1> 	;
  2905                              <1> 	; 08/01/2022
  2906 00002CFD 9C                  <1> 	pushf
  2907 00002CFE E80C000000          <1> 	call	sp_i8
  2908                              <1> 	; 23/10/2015
  2909 00002D03 B8[4D2B0000]        <1> 	mov 	eax, com1_int
  2910 00002D08 A3[60310000]        <1> 	mov	[com1_irq4], eax
  2911                              <1> 	; 26/10/2015
  2912 00002D0D 9D                  <1> 	popf
  2913 00002D0E C3                  <1> 	retn
  2914                              <1> 
  2915                              <1> sp_i8:
  2916                              <1> 	; 08/01/2022
  2917                              <1> 	;pushf
  2918 00002D0F FA                  <1> 	cli
  2919                              <1> 	;
  2920                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2921 00002D10 B2FC                <1> 	mov	dl, 0FCh
  2922 00002D12 EC                  <1> 	in	al, dx 	   		; read register
  2923 00002D13 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2924 00002D15 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2925 00002D17 EE                  <1> 	out	dx, al     		; write back to register
  2926 00002D18 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2927                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2928 00002D1A B2F9                <1> 	mov	dl, 0F9h
  2929 00002D1C EC                  <1> 	in	al, dx     		; read register
  2930 00002D1D EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2931                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2932 00002D1F 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2933 00002D21 EE                  <1> 	out	dx, al 	   		; write back to register
  2934 00002D22 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2935 00002D24 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2936 00002D26 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2937                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2938 00002D28 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2939 00002D2A E621                <1> 	out	21h, al    		; write back to register
  2940                              <1> 	;
  2941                              <1> 	;popf	
  2942 00002D2C C3                  <1> 	retn
  2943                              <1> 
  2944                              <1> sp_invp_err:
  2945 00002D2D C705[D86D0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2945 00002D35 0000                <1>
  2946 00002D37 31C9                <1> 	xor	ecx, ecx
  2947 00002D39 49                  <1> 	dec	ecx ; 0FFFFh
  2948 00002D3A F9                  <1> 	stc
  2949 00002D3B C3                  <1> 	retn
  2950                              <1> 
  2951                              <1> ; 29/10/2015
  2952                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2953 00002D3C 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2954                              <1> 
  2955                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2956                              <1> epoch:
  2957                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2958                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2959                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2960                              <1> 	; 'epoch' procedure prototype: 
  2961                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2962                              <1> 	; 14/11/2012
  2963                              <1> 	; unixboot.asm (boot file configuration)
  2964                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2965                              <1> 	; 21/7/2012
  2966                              <1> 	; 15/7/2012
  2967                              <1> 	; 14/7/2012		
  2968                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2969                              <1> 	; compute current date and time as UNIX Epoch/Time
  2970                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2971                              <1> 	;
  2972                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2973                              <1> 	;
  2974 00002D43 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2975 00002D48 86E9                <1>         xchg 	ch,cl
  2976 00002D4A 66890D[98650000]    <1>         mov 	[hour], cx
  2977 00002D51 86F2                <1>         xchg 	dh,dl
  2978 00002D53 668915[9A650000]    <1>         mov 	[second], dx
  2979                              <1> 	;
  2980 00002D5A E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2981 00002D5F 86E9                <1>         xchg 	ch,cl
  2982 00002D61 66890D[94650000]    <1>         mov 	[year], cx
  2983 00002D68 86F2                <1>         xchg 	dh,dl
  2984 00002D6A 668915[96650000]    <1>         mov 	[month], dx
  2985                              <1> 	;
  2986 00002D71 66B93030            <1> 	mov 	cx, 3030h
  2987                              <1> 	;
  2988 00002D75 A0[98650000]        <1> 	mov 	al, [hour] ; Hour
  2989                              <1>         	; AL <= BCD number)
  2990 00002D7A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2991                              <1> 					; AH = AL / 10h
  2992                              <1> 					; AL = AL MOD 10h
  2993 00002D7C D50A                <1>         aad 	; AX= AH*10+AL
  2994 00002D7E A2[98650000]        <1> 	mov 	[hour], al
  2995 00002D83 A0[99650000]        <1> 	mov 	al, [hour+1] ; Minute
  2996                              <1>         	; AL <= BCD number)
  2997 00002D88 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2998                              <1> 					; AH = AL / 10h
  2999                              <1> 					; AL = AL MOD 10h
  3000 00002D8A D50A                <1>         aad 	; AX= AH*10+AL
  3001 00002D8C A2[99650000]        <1> 	mov 	[minute], al
  3002 00002D91 A0[9A650000]        <1> 	mov 	al, [second] ; Second
  3003                              <1>         	; AL <= BCD number)
  3004 00002D96 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3005                              <1> 					; AH = AL / 10h
  3006                              <1> 					; AL = AL MOD 10h
  3007 00002D98 D50A                <1>         aad 	; AX= AH*10+AL
  3008 00002D9A A2[9A650000]        <1> 	mov 	[second], al
  3009 00002D9F 66A1[94650000]      <1> 	mov 	ax, [year] ; Year (century)
  3010                              <1> 	;push 	ax
  3011                              <1> 	; 04/12/2021
  3012 00002DA5 50                  <1> 	push	eax
  3013                              <1> 	   	; AL <= BCD number)
  3014 00002DA6 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3015                              <1> 					; AH = AL / 10h
  3016                              <1> 					; AL = AL MOD 10h
  3017 00002DA8 D50A                <1>         aad 	; AX= AH*10+AL
  3018 00002DAA B464                <1> 	mov 	ah, 100
  3019 00002DAC F6E4                <1> 	mul 	ah
  3020 00002DAE 66A3[94650000]      <1> 	mov 	[year], ax
  3021                              <1> 	;pop	ax
  3022                              <1> 	; 04/12/2021
  3023 00002DB4 58                  <1> 	pop	eax
  3024 00002DB5 88E0                <1> 	mov	al, ah
  3025                              <1>         	; AL <= BCD number)
  3026 00002DB7 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3027                              <1> 					; AH = AL / 10h
  3028                              <1> 					; AL = AL MOD 10h
  3029 00002DB9 D50A                <1>         aad 	; AX= AH*10+AL
  3030 00002DBB 660105[94650000]    <1> 	add 	[year], ax
  3031 00002DC2 A0[96650000]        <1> 	mov 	al, [month] ; Month
  3032                              <1>            	; AL <= BCD number)
  3033 00002DC7 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3034                              <1> 					; AH = AL / 10h
  3035                              <1> 					; AL = AL MOD 10h
  3036 00002DC9 D50A                <1>         aad 	; AX= AH*10+AL
  3037 00002DCB A2[96650000]        <1> 	mov 	[month], al	
  3038 00002DD0 A0[97650000]        <1>         mov     al, [month+1]      	; Day
  3039                              <1>            	; AL <= BCD number)
  3040 00002DD5 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3041                              <1> 					; AH = AL / 10h
  3042                              <1> 					; AL = AL MOD 10h
  3043 00002DD7 D50A                <1>         aad 	; AX= AH*10+AL
  3044 00002DD9 A2[97650000]        <1>         mov     [day], al
  3045                              <1> 	
  3046                              <1> convert_to_epoch:
  3047                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3048                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3049                              <1> 	;
  3050                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3051                              <1> 	;
  3052                              <1> 	; Derived from DALLAS Semiconductor
  3053                              <1> 	; Application Note 31 (DS1602/DS1603)
  3054                              <1> 	; 6 May 1998
  3055 00002DDE 29C0                <1> 	sub 	eax, eax
  3056 00002DE0 66A1[94650000]      <1> 	mov 	ax, [year]
  3057 00002DE6 662DB207            <1> 	sub 	ax, 1970
  3058 00002DEA BA6D010000          <1> 	mov 	edx, 365
  3059 00002DEF F7E2                <1> 	mul 	edx
  3060 00002DF1 31DB                <1> 	xor 	ebx, ebx
  3061 00002DF3 8A1D[96650000]      <1> 	mov 	bl, [month]
  3062 00002DF9 FECB                <1> 	dec 	bl
  3063 00002DFB D0E3                <1> 	shl 	bl, 1
  3064                              <1> 	;sub	edx, edx
  3065 00002DFD 668B93[9C650000]    <1> 	mov 	dx, [EBX+DMonth]
  3066 00002E04 8A1D[97650000]      <1>         mov     bl, [day]
  3067 00002E0A FECB                <1> 	dec 	bl
  3068 00002E0C 01D0                <1> 	add 	eax, edx
  3069 00002E0E 01D8                <1> 	add 	eax, ebx
  3070                              <1> 			; EAX = days since 1/1/1970
  3071 00002E10 668B15[94650000]    <1> 	mov 	dx, [year]
  3072 00002E17 6681EAB107          <1> 	sub 	dx, 1969
  3073 00002E1C 66D1EA              <1> 	shr 	dx, 1
  3074 00002E1F 66D1EA              <1> 	shr 	dx, 1		
  3075                              <1> 		; (year-1969)/4
  3076 00002E22 01D0                <1> 	add 	eax, edx
  3077                              <1> 			; + leap days since 1/1/1970
  3078 00002E24 803D[96650000]02    <1> 	cmp 	byte [month], 2	; if past february
  3079 00002E2B 7610                <1> 	jna 	short cte1
  3080 00002E2D 668B15[94650000]    <1> 	mov 	dx, [year]
  3081 00002E34 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3082 00002E38 7503                <1> 	jnz 	short cte1		
  3083                              <1> 			; and if leap year
  3084 00002E3A 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3085                              <1> cte1: 			; compute seconds since 1/1/1970
  3086 00002E3D BA18000000          <1> 	mov 	edx, 24
  3087 00002E42 F7E2                <1> 	mul	edx
  3088 00002E44 8A15[98650000]      <1> 	mov 	dl, [hour]
  3089 00002E4A 01D0                <1> 	add 	eax, edx
  3090                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3091                              <1> 	;mov	ebx, 60
  3092 00002E4C B33C                <1> 	mov	bl, 60
  3093 00002E4E F7E3                <1> 	mul	ebx
  3094 00002E50 8A15[99650000]      <1> 	mov 	dl, [minute]
  3095 00002E56 01D0                <1> 	add 	eax, edx
  3096                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3097                              <1> 	;mov 	ebx, 60
  3098 00002E58 F7E3                <1> 	mul	ebx
  3099 00002E5A 8A15[9A650000]      <1> 	mov 	dl, [second]
  3100 00002E60 01D0                <1> 	add 	eax, edx
  3101                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3102 00002E62 C3                  <1> 	retn
  3103                              <1> 
  3104                              <1> get_rtc_time:
  3105                              <1> 	; 15/03/2015
  3106                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3107                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3108                              <1> 	; INT 1Ah
  3109                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3110                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3111                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3112                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3113                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3114                              <1> 	;								
  3115                              <1> RTC_20: 				; GET RTC TIME
  3116 00002E63 FA                  <1> 	cli
  3117 00002E64 E8B6DCFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3118 00002E69 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3119                              <1> 
  3120 00002E6B B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3121 00002E6D E897DCFFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3122 00002E72 88C6                <1> 	MOV	DH, AL			; SAVE
  3123 00002E74 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3124 00002E76 E88EDCFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3125 00002E7B 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3126 00002E7D 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3127 00002E7F B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3128 00002E81 E883DCFFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3129 00002E86 88C1                <1> 	MOV	CL, AL			; SAVE
  3130 00002E88 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3131 00002E8A E87ADCFFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3132 00002E8F 88C5                <1> 	MOV	CH, AL			; SAVE
  3133 00002E91 F8                  <1> 	CLC				; SET CY= 0
  3134                              <1> RTC_29:
  3135 00002E92 FB                  <1> 	sti
  3136 00002E93 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3137                              <1> 
  3138                              <1> get_rtc_date:
  3139                              <1> 	; 15/03/2015
  3140                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3141                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3142                              <1> 	; INT 1Ah
  3143                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3144                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3145                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3146                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3147                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3148                              <1> 	;
  3149                              <1> RTC_40: 				; GET RTC DATE
  3150 00002E94 FA                  <1> 	cli
  3151 00002E95 E885DCFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3152 00002E9A 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3153                              <1> 
  3154 00002E9C B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3155 00002E9E E866DCFFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3156 00002EA3 88C2                <1> 	MOV	DL, AL			; SAVE
  3157 00002EA5 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3158 00002EA7 E85DDCFFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3159 00002EAC 88C6                <1> 	MOV	DH, AL			; SAVE
  3160 00002EAE B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3161 00002EB0 E854DCFFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3162 00002EB5 88C1                <1> 	MOV	CL, AL			; SAVE
  3163 00002EB7 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3164 00002EB9 E84BDCFFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3165 00002EBE 88C5                <1> 	MOV	CH, AL			; SAVE
  3166 00002EC0 F8                  <1> 	CLC				; SET CY=0
  3167                              <1> RTC_49:
  3168 00002EC1 FB                  <1> 	sti
  3169 00002EC2 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3170                              <1> 
  3171                              <1> set_date_time:
  3172                              <1> convert_from_epoch:
  3173                              <1> 	; 02/06/2022 (BugFix)
  3174                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3175                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3176                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3177                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3178                              <1> 	;
  3179                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3180                              <1> 	;
  3181                              <1> 	; Derived from DALLAS Semiconductor
  3182                              <1> 	; Application Note 31 (DS1602/DS1603)
  3183                              <1> 	; 6 May 1998
  3184                              <1> 	;
  3185                              <1> 	; INPUT:
  3186                              <1> 	; EAX = Unix (Epoch) Time
  3187                              <1> 	;
  3188 00002EC3 31D2                <1> 	xor 	edx, edx
  3189                              <1> 	; 02/06/2022
  3190 00002EC5 31C9                <1> 	xor	ecx, ecx
  3191 00002EC7 31DB                <1> 	xor	ebx, ebx
  3192                              <1> 	;mov 	ecx, 60
  3193 00002EC9 B13C                <1> 	mov	cl, 60
  3194 00002ECB F7F1                <1> 	div	ecx
  3195                              <1> 	;mov 	[imin], eax  ; whole minutes
  3196                              <1> 			     ; since 1/1/1970
  3197                              <1> 	;mov 	[second], dx ; leftover seconds
  3198 00002ECD 8815[9A650000]      <1> 	mov	[second], dl ; 02/06/2022
  3199 00002ED3 29D2                <1> 	sub 	edx, edx
  3200 00002ED5 F7F1                <1> 	div	ecx
  3201                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3202                              <1> 	;		     ; since 1/1/1970
  3203                              <1> 	;mov 	[minute], dx ; leftover minutes
  3204 00002ED7 8815[99650000]      <1> 	mov	[minute], dl ; 02/06/2022
  3205 00002EDD 31D2                <1> 	xor	edx, edx
  3206                              <1> 	;mov 	cx, 24
  3207 00002EDF B118                <1> 	mov 	cl, 24
  3208 00002EE1 F7F1                <1> 	div	ecx
  3209                              <1> 	;mov 	[iday], ax   ; whole days
  3210                              <1> 			     ; since 1/1/1970
  3211                              <1> 	;mov 	[hour], dx   ; leftover hours
  3212 00002EE3 8815[98650000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3213                              <1> 
  3214 00002EE9 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3215                              <1> 			     ; 1/1/1968 	
  3216                              <1> 		;mov 	[iday], ax
  3217 00002EEE 50                  <1> 	push 	eax
  3218 00002EEF 29D2                <1> 	sub	edx, edx
  3219 00002EF1 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3220 00002EF6 F7F1                <1> 	div	ecx
  3221 00002EF8 59                  <1> 	pop 	ecx
  3222                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3223                              <1> 	;push	dx
  3224                              <1> 	; 02/06/2022
  3225 00002EF9 52                  <1> 	push 	edx
  3226                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3227 00002EFA 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3228 00002EFE F5                  <1> 	cmc		     ; add this quadyr's leap day
  3229 00002EFF 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3230                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3231                              <1> 	;mov 	cx, [iday]
  3232 00002F02 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3233 00002F03 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3234 00002F05 B96D010000          <1> 	mov 	ecx, 365
  3235 00002F0A 31D2                <1> 	xor	edx, edx
  3236                              <1> 	; EAX = iday-lday, EDX = 0
  3237 00002F0C F7F1                <1> 	div	ecx
  3238                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3239                              <1> 	;jday = iday - (iyrs*365) - lday
  3240                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3241                              <1> 	;add	eax, 1968
  3242 00002F0E 6605B007            <1> 	add 	ax, 1968     ; compute year
  3243 00002F12 66A3[94650000]      <1> 	mov 	[year], ax
  3244                              <1> 	;mov 	cx, dx
  3245                              <1> 	; 02/06/2022
  3246 00002F18 89D1                <1> 	mov	ecx, edx
  3247                              <1> 	;mov 	dx, [qday]
  3248                              <1> 	;pop	dx
  3249                              <1> 	; 02/06/2022
  3250 00002F1A 5A                  <1> 	pop 	edx
  3251 00002F1B 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3252 00002F20 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3253 00002F22 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3254 00002F26 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3255 00002F27 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3256                              <1> cfe1:			
  3257                              <1> 	;mov 	[jday], cx
  3258                              <1> 	;mov 	bx, 12       ; estimate month
  3259                              <1> 	;sub	ebx, ebx
  3260                              <1> 	; 02/06/2022
  3261 00002F2B B30C                <1> 	mov	bl, 12
  3262 00002F2D 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3263 00002F31 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3264                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3265                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3266                              <1> 	; 02/06/2022
  3267 00002F35 39D1                <1> 	cmp	ecx, edx 	 		
  3268 00002F37 7319                <1> 	jnb 	short cfe3
  3269                              <1> 	;dec 	bx           ; month = month - 1
  3270 00002F39 FECB                <1> 	dec	bl			
  3271                              <1> 	;shl 	bx, 1
  3272 00002F3B D0E3                <1> 	shl	bl, 1
  3273 00002F3D 668B93[9C650000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3274                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3275                              <1> 	; 02/06/2022
  3276 00002F44 D0EB                <1> 	shr	bl, 1
  3277 00002F46 80FB01              <1> 	cmp	bl, 1
  3278                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3279 00002F49 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3280 00002F4B 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3281 00002F4D 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3282                              <1> 	;inc 	dx           ; mday = mday + 1
  3283 00002F4F 42                  <1> 	inc	edx
  3284 00002F50 EBE3                <1> 	jmp 	short cfe2
  3285                              <1> cfe3:
  3286                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3287                              <1> 	; 02/06/2022
  3288 00002F52 FEC3                <1> 	inc	bl
  3289                              <1> 	;mov 	[month], bx
  3290 00002F54 881D[96650000]      <1> 	mov	[month], bl
  3291                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1	
  3292 00002F5A 29D1                <1> 	sub	ecx, edx
  3293                              <1> 	;inc 	cx 			  
  3294 00002F5C FEC1                <1> 	inc	cl
  3295                              <1> 	;mov 	[day], cx
  3296 00002F5E 880D[97650000]      <1> 	mov	[day], cl    ; 02/06/2022
  3297                              <1> 
  3298                              <1> 	; eax, ebx, ecx, edx is changed at return
  3299                              <1> 	; output ->
  3300                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3301                              <1> 	
  3302                              <1> 	; 02/06/2022 (BugFix)	
  3303                              <1> _set_date:
  3304 00002F64 66A1[94650000]      <1> 	mov	ax, [year]
  3305 00002F6A B520                <1> 	mov	ch, 20h ; century (bcd)
  3306 00002F6C 662DD007            <1> 	sub	ax, 2000
  3307 00002F70 7306                <1> 	jnc	short set_date
  3308 00002F72 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3309 00002F74 6683C064            <1> 	add	ax, 100	
  3310                              <1> 	; 02/06/2022
  3311                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3312                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3313                              <1> set_date:
  3314                              <1>         ;mov	al, [year+1]
  3315                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3316                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3317                              <1> 	;		     ; AL = AH * 10h + AL
  3318                              <1> 	;mov 	ch, al ; century (BCD)
  3319                              <1> 	;mov 	al, [year]
  3320                              <1> 	; al = year (0-99) ; 01/06/2022
  3321 00002F78 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3322 00002F7A D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3323                              <1> 			     ; AL = AH * 10h + AL
  3324 00002F7C 88C1                <1> 	mov 	cl, al ; year (BCD)
  3325 00002F7E A0[96650000]        <1>         mov 	al, [month]
  3326 00002F83 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3327 00002F85 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3328                              <1> 			     ; AL = AH * 10h + AL
  3329 00002F87 88C6                <1> 	mov 	dh, al ; month (BCD)
  3330 00002F89 A0[97650000]        <1> 	mov 	al, [day]
  3331 00002F8E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3332 00002F90 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3333                              <1> 			     ; AL = AH * 10h + AL
  3334                              <1> 	; 02/06/2022 (BugFix)
  3335 00002F92 88C2                <1> 	mov 	dl, al ; day (BCD)
  3336                              <1> 
  3337                              <1> 	; Set real-time clock date
  3338 00002F94 E879000000          <1> 	call	set_rtc_date
  3339                              <1> set_time:
  3340                              <1>         ; Read real-time clock time 
  3341                              <1> 	; (get day light saving time bit status)
  3342 00002F99 FA                  <1>  	cli
  3343 00002F9A E880DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3344                              <1> 	; cf = 1 -> al = 0
  3345 00002F9F 7207                <1>         jc      short stime1
  3346 00002FA1 B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3347 00002FA3 E861DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3348                              <1> stime1:
  3349 00002FA8 FB                  <1> 	sti
  3350 00002FA9 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3351 00002FAB 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3352                              <1> 	; DL = 1 or 0 (day light saving time)
  3353                              <1> 	;	
  3354 00002FAD A0[98650000]        <1> 	mov 	al, [hour]
  3355 00002FB2 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3356 00002FB4 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3357                              <1> 			     ; AL = AH * 10h + AL
  3358 00002FB6 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3359 00002FB8 A0[99650000]        <1>         mov     al, [minute]
  3360 00002FBD D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3361 00002FBF D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3362                              <1> 			     ; AL = AH * 10h + AL
  3363 00002FC1 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3364 00002FC3 A0[9A650000]        <1>         mov     al, [second]
  3365 00002FC8 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3366 00002FCA D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3367                              <1> 			     ; AL = AH * 10h + AL
  3368 00002FCC 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3369                              <1> 
  3370                              <1> 	; Set real-time clock time
  3371                              <1>  	; call	set_rtc_time
  3372                              <1> set_rtc_time:
  3373                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3374                              <1> 	; 15/03/2015
  3375                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3376                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3377                              <1> 	; INT 1Ah
  3378                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3379                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3380                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3381                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3382                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3383                              <1> 	;								:
  3384                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3385                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3386                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3387                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3388                              <1> 	;
  3389                              <1> RTC_30: 				; SET RTC TIME
  3390 00002FCE FA                  <1> 	cli
  3391 00002FCF E84BDBFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3392 00002FD4 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3393 00002FD6 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3394                              <1> RTC_35:
  3395 00002FDB 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3396 00002FDD B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3397 00002FDF E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3398 00002FE4 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3399 00002FE6 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3400 00002FE8 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3401 00002FED 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3402 00002FEF B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3403 00002FF1 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3404                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3405 00002FF6 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3406 00002FFA E80ADBFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3407 00002FFF 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3408 00003001 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3409 00003003 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3410 00003006 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3411 00003008 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3412 0000300A E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3413 0000300F F8                  <1> 	CLC				; SET CY= 0
  3414 00003010 FB                  <1> 	sti
  3415 00003011 C3                  <1> 	RETn				; RETURN WITH CY= 0
  3416                              <1> 
  3417                              <1> set_rtc_date:
  3418                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3419                              <1> 	; 15/03/2015
  3420                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3421                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3422                              <1> 	; INT 1Ah
  3423                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3424                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3425                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3426                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3427                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3428                              <1> 	;
  3429                              <1> RTC_50: 				; SET RTC DATE
  3430 00003012 FA                  <1> 	cli
  3431 00003013 E807DBFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3432 00003018 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3433 0000301A E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3434                              <1> RTC_55:
  3435 0000301F 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3436 00003023 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3437 00003028 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3438 0000302A B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3439 0000302C E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3440 00003031 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3441 00003033 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3442 00003035 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3443 0000303A 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3444 0000303C B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3445 0000303E E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3446 00003043 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3447 00003045 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3448 00003047 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3449                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3450 0000304C 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3451 00003050 E8B4DAFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3452 00003055 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3453 00003057 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3454 00003059 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3455 0000305E F8                  <1> 	CLC				; SET CY= 0
  3456 0000305F FB                  <1> 	sti
  3457 00003060 C3                  <1> 	RETn				; RETURN CY=0
  3458                              <1> 
  3459                              <1> 	; 15/03/2015
  3460                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3461 00003061 B426                <1> 	mov	ah, 26h
  3462 00003063 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3463 00003065 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3464 0000306A B482                <1> 	mov	ah, 82h
  3465 0000306C B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3466 0000306E E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3467 00003073 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3468 00003075 E88FDAFFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3469 0000307A B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3470                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3471                              <1> 	;RETn
  3472                              <1> 	; 06/02/2022
  3473 0000307C E988DAFFFF          <1> 	jmp	CMOS_READ
  3474                              <1> 
  3475                              <1> 	; 15/03/2015
  3476                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3477                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3478 00003081 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3479                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3480 00003082 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3481 00003084 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3482 00003085 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3483 00003087 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3484 00003088 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3485 0000308A 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3486 0000308C E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3487 0000308E B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3488 00003090 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3489 00003092 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3490 00003094 90                  <1> 	nop			; I/O DELAY
  3491 00003095 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3492                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3493 00003097 9D                  <1> 	popf	
  3494 00003098 C3                  <1> 	RETn
  3495                              <1> 
  3496                              <1> bf_init:
  3497                              <1> 	; 21/03/2022 (Retro UNIX 386 v1.2)
  3498                              <1> 	; 28/11/2021
  3499                              <1> 	; 14/08/2015
  3500                              <1> 	; 02/07/2015
  3501                              <1> 	; 01/07/2015
  3502                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3503                              <1> 	; Buffer (pointer) initialization !
  3504                              <1> 	; 
  3505                              <1> 	; 17/07/2013 - 24/07/2013
  3506                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3507                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3508                              <1> 	;
  3509 00003099 BF[F46C0000]        <1> 	mov	edi, bufp 
  3510 0000309E B8[A4980000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3511 000030A3 29D2                <1> 	sub	edx, edx
  3512 000030A5 FECA                <1> 	dec	dl
  3513 000030A7 31C9                <1> 	xor	ecx, ecx
  3514 000030A9 49                  <1> 	dec	ecx
  3515                              <1> bi0:
  3516 000030AA 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3517 000030AF AB                  <1> 	stosd
  3518 000030B0 89C6                <1> 	mov	esi, eax
  3519 000030B2 8916                <1> 	mov	[esi], edx ; 000000FFh
  3520                              <1> 			    ; Not a valid device sign
  3521 000030B4 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3522                              <1> 		      ; Not a valid block number sign 	 	
  3523 000030B7 3D[24780000]        <1> 	cmp	eax, buffer
  3524 000030BC 77EC                <1> 	ja	short bi0
  3525 000030BE B8[0C6E0000]        <1> 	mov	eax, sb0
  3526 000030C3 AB                  <1> 	stosd
  3527 000030C4 B8[14700000]        <1> 	mov	eax, sb1
  3528 000030C9 AB                  <1> 	stosd
  3529 000030CA 89C6                <1> 	mov	esi, eax ; offset sb1
  3530 000030CC 8916                <1> 	mov	[esi], edx ; 000000FFh
  3531                              <1> 			   ; Not a valid device sign
  3532 000030CE 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3533                              <1> 		      ; Not a valid block number sign 	 
  3534                              <1> 	; 14/08/2015
  3535                              <1> 	;call 	rdev_init
  3536                              <1> 	;retn
  3537                              <1> 
  3538                              <1> ; ----- Root file system initialization
  3539                              <1> 	
  3540                              <1> 	; 21/03/2022 - Retro UNIX 386 v1.2
  3541                              <1> 	;	(Retro UNIX -runix- v2 file system) 
  3542                              <1> 	; 28/11/2021
  3543                              <1> rdev_init: ; root device, super block buffer initialization
  3544                              <1> 	; 14/08/2015
  3545                              <1> 	; Retro UNIX 386 v1 feature only !
  3546                              <1> 	;
  3547                              <1> 	; NOTE: Disk partitions (file systems), logical
  3548                              <1> 	; drive initialization, partition's start sector etc.
  3549                              <1> 	; will be coded here, later in 'ldrv_init'	
  3550                              <1> 
  3551 000030D1 0FB605[48630000]    <1> 	movzx	eax, byte [boot_drv]
  3552                              <1> rdi_0:
  3553 000030D8 3C80                <1> 	cmp	al, 80h
  3554 000030DA 7202                <1> 	jb	short rdi_1
  3555 000030DC 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3556                              <1> rdi_1:
  3557 000030DE A2[426D0000]        <1> 	mov	[rdev], al
  3558                              <1> 	; 21/03/2022
  3559                              <1> 	;cmp	al, 2
  3560                              <1> 	;jnb	short rdi_2
  3561 000030E3 08C0                <1> 	or	al, al
  3562 000030E5 7504                <1> 	jnz	short rdi_2 ; hard disk boot
  3563                              <1> 	; floppy disk boot
  3564 000030E7 31D2                <1> 	xor	edx, edx ; device number = 0
  3565                              <1> 			 ; (& fglags = 0)
  3566                              <1> 	; eax = 0 ; boot sector address = 0
  3567                              <1> 	;jmp	short rdi_5
  3568 000030E9 EB22                <1> 	jmp	short rdi_4
  3569                              <1> rdi_2:
  3570                              <1> 	; load masterboot sector
  3571                              <1> 	; to get runix v2 partition's boot sector address
  3572                              <1> 	;	
  3573 000030EB BB[1C720000]        <1> 	mov	ebx, mbrbuf ; masterboot buffer header addr
  3574                              <1> 	;mov	[ebx], eax
  3575 000030F0 8803                <1> 	mov	[ebx], al
  3576                              <1> 	;sub	al, al
  3577                              <1> 	;; eax = 0
  3578                              <1> 	;mov	[ebx+4], eax ; masterboot sector address
  3579 000030F2 E8D72A0000          <1> 	call	diskio
  3580 000030F7 730A                <1> 	jnc	short rdi_3
  3581                              <1> rdi_err:
  3582 000030F9 BE[20310000]        <1> 	mov	esi, disk_read_err_msg
  3583 000030FE E9B6F9FFFF          <1> 	jmp	key_to_reboot
  3584                              <1> 
  3585                              <1> rdi_3:
  3586                              <1> 	; [ebx+8] = masterboot buffer (data) address 
  3587                              <1> 	;cmp	word [ebx+8+510], 0AA55h
  3588                              <1> 	;jc	short rdi_err
  3589                              <1> 
  3590 00003103 8D7308              <1> 	lea	esi, [ebx+8] 
  3591 00003106 E82D000000          <1> 	call	runix_p_bs    ; return start sector address of
  3592                              <1> 			      ; retro unix v2 partition in esi
  3593                              <1> 	;;jc	short rdi_err ; 'retn'
  3594                              <1> 	;jnc	short rdi_4 ; Runix v2 partition not found !?
  3595                              <1> 			    ; 21/03/2022	
  3596                              <1> 			    ; ((Here, if cf is 1, that means,
  3597                              <1> 			    ; runix v2 partition not found
  3598                              <1> 			    ; in the MBR partition table.
  3599                              <1> 			    ; But, at least, there is a valid
  3600                              <1> 			    ; runix v2 boot sector on the disk
  3601                              <1> 			    ; which started the kernel.
  3602                              <1> 			    ; So, runix v2 boot sector code
  3603                              <1> 			    ; may -must- be on physical sector 0
  3604                              <1> 			    ; and then the superblock may be
  3605                              <1> 			    ; -must be- on physical sector 1.)) 
  3606                              <1> 	;sub	eax, eax
  3607                              <1> 	; eax = 0
  3608                              <1> ;rdi_4:
  3609 0000310B 8B13                <1> 	mov	edx, [ebx] ; restore device number in dl
  3610                              <1> ;rdi_5:
  3611                              <1> rdi_4:
  3612 0000310D BB[0C6E0000]        <1>         mov	ebx, sb0 ; super block buffer (header)
  3613                              <1> 
  3614 00003112 40                  <1> 	inc	eax	; default sector address of the sb
  3615                              <1> 			; (boot sector address + 1)
  3616                              <1> 
  3617                              <1> 	;mov 	[ebx], eax
  3618                              <1> 	;mov	al, 1 ; eax = 1
  3619                              <1> 	;mov	[ebx+4], eax ; super block address on disk
  3620                              <1> 	; 21/03/2022
  3621 00003113 8913                <1> 	mov	[ebx], edx ; device number in DL
  3622                              <1> 			   ; (other bytes -flags- are zero)
  3623 00003115 894304              <1> 	mov	[ebx+4], eax ; superblock address on disk
  3624                              <1> 
  3625                              <1> 	;call 	diskio
  3626                              <1> 	;retn
  3627                              <1> 	; 28/11/2021
  3628                              <1> 	;jmp	diskio
  3629                              <1> 
  3630                              <1> 	; 21/03/2022
  3631 00003118 E8B12A0000          <1> 	call	diskio
  3632 0000311D 72DA                <1> 	jc	short rdi_err
  3633                              <1> 
  3634                              <1> 	; 21/03/2022
  3635                              <1> 	; Note: If superblock is defective or SB sector
  3636                              <1> 	;	address is wrong, "ERROR: /etc/init !?"
  3637                              <1> 	;	message will appear after here.
  3638                              <1> 	;	..because /etc/init inode will not be found..
  3639                              <1> 	;	So, i am not writing SB validation
  3640                              <1> 	;	(check) code here.
  3641                              <1> 	;
  3642                              <1> 	; ((Also, if we are here, everything should be normal!))
  3643                              <1> 
  3644 0000311F C3                  <1> 	retn
  3645                              <1> 
  3646                              <1> disk_read_err_msg:
  3647                              <1> 	; 21/03/2022 - Retro UNIX 386 v1.2
  3648 00003120 070D0A              <1> 	db 07h, 0Dh, 0Ah
  3649 00003123 4469736B2072656164- <1> 	db "Disk read error ! "
  3649 0000312C 206572726F72202120  <1>
  3650 00003135 0D0A00              <1> 	db 0Dh, 0Ah, 0
  3651                              <1> 
  3652                              <1> 	; 21/03/2022 - Retro UNIX 386 v1.2
  3653                              <1> runix_p_bs:
  3654                              <1> 	; get retro unix v2 partition's boot sector address
  3655                              <1> 	
  3656                              <1> 	; 09/05/2021
  3657                              <1> 	; 19/04/2021 - Retro UNIX 386 v2
  3658                              <1> 	; INPUT:
  3659                              <1> 	;	;;Masterboot buffer at offset mbrbuf
  3660                              <1> 	;	; 21/03/2022
  3661                              <1> 	;	esi = Masterboot buffer (data) address
  3662                              <1> 	; OUTPUT:
  3663                              <1> 	;	;;esi = start sector addr of retro unix v2 fs
  3664                              <1> 	;	; 21/03/2022
  3665                              <1> 	;	eax = start sector address of retro unix v2 fs
  3666                              <1> 	;
  3667                              <1> 	;	cf = 1 -> error, retro unix fs not found
  3668                              <1> 	;		(eax = 0)	
  3669                              <1> 	;
  3670                              <1> 	; Modified registers: esi, eax
  3671                              <1> 
  3672                              <1> 	ptBootable       equ 0
  3673                              <1> 	ptBeginHead      equ 1
  3674                              <1> 	ptBeginSector    equ 2
  3675                              <1> 	ptBeginCylinder  equ 3
  3676                              <1> 	ptFileSystemID   equ 4
  3677                              <1> 	ptEndHead        equ 5
  3678                              <1> 	ptEndSector      equ 6
  3679                              <1> 	ptEndCylinder    equ 7
  3680                              <1> 	ptStartSector    equ 8
  3681                              <1> 	ptSectors        equ 12
  3682                              <1> 
  3683                              <1> 	FS_RETROUNIX	 equ 71h ; runix v2 partition ID
  3684                              <1> 
  3685                              <1> 	;cmp	word [mbrbuf+510], 0AA55h
  3686 00003138 6681BEFE01000055AA  <1> 	cmp	word [esi+510], 0AA55h
  3687 00003141 7515                <1> 	jne	short runix_p_nf
  3688                              <1> 
  3689                              <1> 	; partition table entries are at offset 1BEh
  3690                              <1> 	;mov	esi, mbrbuf+1BEh+ptFileSystemID
  3691 00003143 81C6C2010000        <1> 	add	esi, 1BEh+ptFileSystemID
  3692 00003149 8D4640              <1> 	lea	eax, [esi+(4*16)] 
  3693                              <1> runix_p_bs_0:
  3694 0000314C 803E71              <1> 	cmp	byte [esi], FS_RETROUNIX ; 71h
  3695 0000314F 740B                <1> 	je	short runix_p_f ; it is retro unix partition
  3696 00003151 83C610              <1> 	add	esi, 16
  3697                              <1> 	;cmp	esi, mbrbuf+1BEh+ptFileSystemID+(4*16) 
  3698 00003154 39C6                <1> 	cmp	esi, eax
  3699 00003156 72F4                <1> 	jb	short runix_p_bs_0 	  
  3700                              <1> runix_p_nf:
  3701 00003158 29C0                <1> 	sub	eax, eax
  3702                              <1> 	; eax = 0
  3703 0000315A F9                  <1> 	stc
  3704 0000315B C3                  <1> 	retn
  3705                              <1> runix_p_f:
  3706                              <1> 	;mov	esi, [esi+ptStartSector-ptFileSystemID]
  3707 0000315C 8B4604              <1> 	mov	eax, [esi+ptStartSector-ptFileSystemID]
  3708 0000315F C3                  <1> 	retn
  3709                              <1> 
  3710                              <1> ; 23/10/2015
  3711                              <1> com1_irq4:
  3712 00003160 [68310000]          <1> 	dd dummy_retn
  3713                              <1> com2_irq3:
  3714 00003164 [68310000]          <1> 	dd dummy_retn
  3715                              <1> 
  3716                              <1> dummy_retn:
  3717 00003168 C3                  <1> 	retn
  2087                                  %include 'u1.s'      ; 10/05/2015
  2088                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2089                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2090                              <1> ; ****************************************************************************
  2091                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2092                              <1> ; Last Modification: 18/04/2022 (Retro UNIX 386 v1.2)
  2093                              <1> ; ----------------------------------------------------------------------------
  2094                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2095                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2096                              <1> ;
  2097                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2098                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2099                              <1> ; <Bell Laboratories (17/3/1972)>
  2100                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2101                              <1> ;
  2102                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2103                              <1> ;
  2104                              <1> ; ****************************************************************************
  2105                              <1> 
  2106                              <1> unkni: ; / used for all system calls
  2107                              <1> sysent: ; < enter to system call >
  2108                              <1> 	; 25/12/2021 (Retro UNIX 386 v1.2)
  2109                              <1> 	; 19/10/2015
  2110                              <1> 	; 21/09/2015
  2111                              <1> 	; 01/07/2015
  2112                              <1> 	; 19/05/2015
  2113                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2114                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2115                              <1> 	;
  2116                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2117                              <1> 	; The trap type is determined and an indirect jump is made to 
  2118                              <1> 	; the appropriate system call handler. If there is a trap inside
  2119                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2120                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2121                              <1> 	; instructor is decoded to get the the system code part (see
  2122                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2123                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2124                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2125                              <1> 	; is called. If the call is legitimate control passes to the
  2126                              <1> 	; appropriate system routine.
  2127                              <1> 	;
  2128                              <1> 	; Calling sequence:
  2129                              <1> 	;	Through a trap caused by any sys call outside the system.
  2130                              <1> 	; Arguments:
  2131                              <1> 	;	Arguments of particular system call.	
  2132                              <1> 	; ...............................................................
  2133                              <1> 	;	
  2134                              <1> 	; Retro UNIX 8086 v1 modification: 
  2135                              <1> 	;       System call number is in EAX register.
  2136                              <1> 	;
  2137                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2138                              <1> 	;	registers depending of function details.
  2139                              <1>   	;
  2140                              <1> 	; 16/04/2015
  2141 00003169 368925[5C6D0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2142                              <1> 	; save user registers
  2143 00003170 1E                  <1> 	push	ds
  2144 00003171 06                  <1> 	push	es
  2145 00003172 0FA0                <1> 	push	fs
  2146 00003174 0FA8                <1> 	push	gs
  2147 00003176 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2148                              <1> 	;
  2149                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2150                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2151                              <1> 	;	for saving/restoring user registers.)
  2152                              <1> 	;
  2153 00003177 50                  <1> 	push	eax ; 01/07/2015
  2154 00003178 66B81000            <1> 	mov     ax, KDATA
  2155 0000317C 8ED8                <1>         mov     ds, ax
  2156 0000317E 8EC0                <1>         mov     es, ax
  2157 00003180 8EE0                <1>         mov     fs, ax
  2158 00003182 8EE8                <1>         mov     gs, ax
  2159 00003184 A1[28680000]        <1> 	mov	eax, [k_page_dir]
  2160 00003189 0F22D8              <1> 	mov	cr3, eax
  2161 0000318C 58                  <1> 	pop	eax ; 01/07/2015
  2162                              <1> 	; 19/10/2015
  2163 0000318D FC                  <1> 	cld
  2164                              <1> 	;
  2165 0000318E FE05[586D0000]      <1> 	inc	byte [sysflg]
  2166                              <1> 		; incb sysflg / indicate a system routine is in progress
  2167 00003194 FB                  <1>         sti 	; 18/01/2014
  2168                              <1> 	;jnz	panic ; 24/05/2013
  2169                              <1> 	; 04/12/2021
  2170 00003195 7405                <1> 	jz	short _1
  2171 00003197 E918F9FFFF          <1> 	jmp	panic
  2172                              <1> 		; beq 1f
  2173                              <1> 		; jmp panic ; / called if trap inside system
  2174                              <1> ;1:
  2175                              <1> _1:	; 04/12/2021
  2176                              <1> 	; 16/04/2015
  2177 0000319C A3[646D0000]        <1> 	mov	[u.r0], eax
  2178 000031A1 8925[606D0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2179                              <1> 	;
  2180                              <1> 		; mov $s.syst+2,clockp
  2181                              <1> 		; mov r0,-(sp) / save user registers 
  2182                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2183                              <1> 			   ; / in u.r0
  2184                              <1> 		; mov r1,-(sp)
  2185                              <1> 		; mov r2,-(sp)
  2186                              <1> 		; mov r3,-(sp)
  2187                              <1> 		; mov r4,-(sp)
  2188                              <1> 		; mov r5,-(sp)
  2189                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2190                              <1> 		             ; / arithmetic unit
  2191                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2192                              <1> 		             ; / extended arithmetic unit
  2193                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2194                              <1> 		             ; / arithmetic unit
  2195                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2196                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2197                              <1> 		; mov -(r0),r0 / sys inst in r0 10400xxx
  2198                              <1> 		; sub $sys,r0 / get xxx code
  2199 000031A7 C1E002              <1> 	shl	eax, 2
  2200                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2201 000031AA 3DA0000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2202                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2203                              <1> 	;jnb	short badsys
  2204                              <1> 		; bhis badsys / yes, bad system call
  2205                              <1> 	; 25/12/2021
  2206 000031AF 7205                <1> 	jb	short _2
  2207 000031B1 E969010000          <1> 	jmp	badsys
  2208                              <1> _2:
  2209                              <1> 	; 25/12/2021
  2210                              <1> 	;cmc
  2211                              <1> 	;pushf	
  2212                              <1> 	;push	eax
  2213 000031B6 8B2D[5C6D0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2214                              <1> 	;mov	al, 0FEh ; 11111110b
  2215                              <1> 	;;adc	al, 0 ; al = al + cf
  2216                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2217 000031BC 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2218                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2219                              <1> 				 ; / and clear carry bit
  2220                              <1> 	;pop	ebp ; eax
  2221 000031C0 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2222                              <1> 	;popf
  2223                              <1>         ;;jc	badsys
  2224                              <1> 	;; 04/12/2021
  2225                              <1> 	;jnc	short _3
  2226                              <1> 	;jmp	badsys
  2227                              <1> ;_3:
  2228 000031C2 A1[646D0000]        <1> 	mov	eax, [u.r0]
  2229                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2230 000031C7 FFA5[CD310000]      <1> 	jmp	dword [ebp+syscalls]
  2231                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2232                              <1> 		            ; / to proper system routine.
  2233                              <1> 
  2234                              <1> 	; 09/01/2022
  2235                              <1> 	; 01/01/2022 (/etc/init error, BugFix efforts, test)
  2236                              <1> syscalls: ; 1:
  2237                              <1> 	; 21/09/2015
  2238                              <1> 	; 01/07/2015
  2239                              <1> 	; 16/04/2015 (32 bit address modification) 
  2240 000031CD [E9320000]          <1> 	dd sysrele	; / 0
  2241 000031D1 [91330000]          <1> 	dd sysexit 	; / 1
  2242 000031D5 [BC340000]          <1> 	dd sysfork 	; / 2
  2243 000031D9 [C1350000]          <1> 	dd sysread 	; / 3
  2244 000031DD [D6350000]          <1> 	dd syswrite 	; / 4
  2245 000031E1 [39360000]          <1> 	dd sysopen 	; / 5
  2246 000031E5 [62370000]          <1> 	dd sysclose 	; / 6
  2247 000031E9 [37340000]          <1> 	dd syswait 	; / 7
  2248 000031ED [CA360000]          <1> 	dd syscreat 	; / 8
  2249 000031F1 [183B0000]          <1> 	dd syslink 	; / 9
  2250 000031F5 [A63B0000]          <1> 	dd sysunlink 	; / 10
  2251 000031F9 [C63C0000]          <1> 	dd sysexec 	; / 11
  2252 000031FD [33430000]          <1> 	dd syschdir 	; / 12
  2253 00003201 [35440000]          <1> 	dd systime 	; / 13
  2254 00003205 [11370000]          <1> 	dd sysmkdir 	; / 14
  2255 00003209 [72430000]          <1> 	dd syschmod 	; / 15
  2256 0000320D [A1430000]          <1> 	dd syschown 	; / 16
  2257 00003211 [69440000]          <1> 	dd sysbreak 	; / 17
  2258 00003215 [69400000]          <1> 	dd sysstat 	; / 18
  2259 00003219 [79450000]          <1> 	dd sysseek 	; / 19
  2260 0000321D [8B450000]          <1> 	dd systell 	; / 20
  2261 00003221 [34550000]          <1> 	dd sysmount 	; / 21
  2262 00003225 [4D560000]          <1> 	dd sysumount 	; / 22
  2263 00003229 [FC450000]          <1> 	dd syssetuid 	; / 23
  2264 0000322D [31460000]          <1> 	dd sysgetuid 	; / 24
  2265 00003231 [44440000]          <1> 	dd sysstime 	; / 25
  2266 00003235 [F0450000]          <1> 	dd sysquit 	; / 26
  2267 00003239 [E4450000]          <1> 	dd sysintr 	; / 27
  2268 0000323D [50400000]          <1> 	dd sysfstat 	; / 28
  2269 00003241 [7D370000]          <1> 	dd sysemt 	; / 29
  2270 00003245 [CB370000]          <1> 	dd sysmdate 	; / 30
  2271 00003249 [28380000]          <1> 	dd sysstty 	; / 31
  2272 0000324D [123A0000]          <1> 	dd sysgtty 	; / 32
  2273 00003251 [C6370000]          <1> 	dd sysilgins 	; / 33
  2274 00003255 [F85D0000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2275                              <1> 			     ; 11/06/2014
  2276 00003259 [255E0000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2277                              <1> 			     ; 01/07/2015
  2278 0000325D [FD5E0000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2279                              <1> 			     ; 21/09/2015 - get last error number
  2280                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  2281                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  2282 00003261 [4A460000]          <1> 	dd syssetgid	; 37
  2283 00003265 [6D460000]          <1> 	dd sysgetgid	; 38
  2284                              <1> 	; 18/06/2021 - Retro UNIX 386 v2 (ref: TRDOS 386 v2)
  2285 00003269 [82460000]          <1> 	dd sysver	; 39 ; (get) Retro Unix 386 version
  2286                              <1> 
  2287                              <1> end_of_syscalls:
  2288                              <1> 
  2289                              <1> error:
  2290                              <1> 	; 11/12/2021 (Retro UNIX 386 v1.2)
  2291                              <1> 	; 17/09/2015
  2292                              <1> 	; 03/09/2015
  2293                              <1> 	; 01/09/2015
  2294                              <1> 	; 09/06/2015
  2295                              <1> 	; 13/05/2015
  2296                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2297                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2298                              <1> 	;
  2299                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2300                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2301                              <1> 	;
  2302                              <1> 	; INPUTS -> none
  2303                              <1> 	; OUTPUTS ->
  2304                              <1> 	;	processor status - carry (c) bit is set (means error)
  2305                              <1> 	;
  2306                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2307                              <1> 	; 	      Because, jumps to error procedure
  2308                              <1> 	;	      disrupts push-pop nesting balance)
  2309                              <1> 	;
  2310 0000326D 8B2D[5C6D0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2311 00003273 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2312                              <1> 				 ; (system call will return with cf = 1)
  2313                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2314                              <1> 		               ; / users stack
  2315                              <1> 	; 17/09/2015
  2316 00003277 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2317                              <1> 				 ; for saving/restoring user registers	
  2318                              <1> 	;cmp	ebp, [u.usp]
  2319                              <1> 	;je	short err0	
  2320 0000327A 892D[606D0000]      <1> 	mov	[u.usp], ebp
  2321                              <1> ;err0:
  2322                              <1> 	; 01/09/2015
  2323 00003280 8B25[606D0000]      <1> 	mov	esp, [u.usp]	; Retro Unix 8086 v1 modification!
  2324                              <1> 				; 10/04/2013
  2325                              <1> 				; (If an I/O error occurs during disk I/O,
  2326                              <1> 				; related procedures will jump to 'error'
  2327                              <1> 				; procedure directly without returning to 
  2328                              <1> 				; the caller procedure. So, stack pointer
  2329                              <1> 				; must be restored here.)
  2330                              <1> 	; 13/05/2015
  2331                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2332                              <1> 	;	'get last error' system call later. 	
  2333                              <1> 
  2334                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2335 00003286 C605[D66D0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2336                              <1> 
  2337                              <1> sysret: ; < return from system call>
  2338                              <1> 	; 11/12/2021
  2339                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2340                              <1> 	; 30/11/2021
  2341                              <1> 	; 10/09/2015
  2342                              <1> 	; 29/07/2015
  2343                              <1> 	; 25/06/2015
  2344                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2345                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2346                              <1> 	;
  2347                              <1> 	; 'sysret' first checks to see if process is about to be 
  2348                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2349                              <1> 	; If not, following happens:	 
  2350                              <1> 	; 	1) The user's stack pointer is restored.
  2351                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2352                              <1> 	;	   i-node has been modified. If it has, it is written out
  2353                              <1> 	;	   via 'ppoke'.
  2354                              <1> 	;	3) If the super block has been modified, it is written out
  2355                              <1> 	;	   via 'ppoke'.				
  2356                              <1> 	;	4) If the dismountable file system's super block has been
  2357                              <1> 	;	   modified, it is written out to the specified device
  2358                              <1> 	;	   via 'ppoke'.
  2359                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2360                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2361                              <1> 	;	   another user a chance to run.
  2362                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2363                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2364                              <1> 	;
  2365                              <1> 	; Calling sequence:
  2366                              <1> 	;	jump table or 'br sysret'
  2367                              <1> 	; Arguments: 
  2368                              <1> 	;	-	
  2369                              <1> 	; ...............................................................
  2370                              <1> 	;	
  2371                              <1> 	; ((AX=r1 for 'iget' input))
  2372                              <1> 	;	
  2373                              <1> 	;xor	ax, ax ; 04/05/2013
  2374                              <1> 	; 30/11/2021
  2375 0000328D 31C0                <1> 	xor	eax, eax
  2376                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2377 0000328F FEC0                <1> 	inc	al ; 04/05/2013
  2378 00003291 3805[B46D0000]      <1> 	cmp	[u.bsys], al ; 1
  2379                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2380                              <1> 	;jnb	sysexit ; 04/05/2013
  2381                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2382                              <1> 	; 04/12/2021
  2383 00003297 720F                <1> 	jb	short _3
  2384                              <1> 	; 11/12/2021
  2385 00003299 C705[D86D0000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2385 000032A1 0000                <1>
  2386 000032A3 E9E9000000          <1> 	jmp	sysexit
  2387                              <1> _3:
  2388                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2389                              <1> 		; mov u.sp,sp / no point stack to users stack
  2390 000032A8 FEC8                <1> 	dec 	al ; mov ax, 0
  2391                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2392 000032AA E8D6190000          <1> 	call	iget
  2393                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2394                              <1> 		            ; / it is written out
  2395                              <1> 	;xor 	ax, ax ; 0
  2396                              <1> 	; 30/11/2021
  2397 000032AF 31C0                <1> 	xor	eax, eax
  2398 000032B1 3805[566D0000]      <1> 	cmp	[smod], al ; 0
  2399                              <1> 		; tstb	smod / has the super block been modified
  2400 000032B7 7614                <1> 	jna	short sysret1
  2401                              <1> 		; beq	1f / no, 1f
  2402 000032B9 A2[566D0000]        <1> 	mov	[smod], al ; 0
  2403                              <1> 		; clrb smod / yes, clear smod
  2404 000032BE BB[0C6E0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2405 000032C3 66810B0002          <1>    	or	word [ebx], 200h ;;
  2406                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2407                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2408                              <1> 		      	      ; / output
  2409                              <1> 	; AX = 0
  2410 000032C8 E865280000          <1> 	call 	poke ; 07/08/2013
  2411                              <1> 	;call	ppoke
  2412                              <1> 	; AX = 0
  2413                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2414                              <1> sysret1: ;1:
  2415 000032CD 3805[576D0000]      <1> 	cmp	[mmod], al ; 0
  2416                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2417                              <1> 		           ; / system
  2418 000032D3 7614                <1> 	jna	short sysrel0
  2419                              <1> 		; beq 1f / been modified?  no, 1f
  2420 000032D5 A2[576D0000]        <1> 	mov	[mmod], al ; 0	
  2421                              <1> 		; clrb	mmod / yes, clear mmod
  2422                              <1>         ;mov    ax, [mntd]
  2423                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2424 000032DA BB[14700000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2425                              <1>         ;;mov	[ebx], al
  2426                              <1> 	;mov    [sb1], al
  2427                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2428 000032DF 66810B0002          <1> 	or	word [ebx], 200h
  2429                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2430                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2431 000032E4 E849280000          <1> 	call	poke ; 07/08/2013
  2432                              <1> 	;call	ppoke 
  2433                              <1> 		; jsr r0,ppoke / write it out to its device
  2434                              <1>         ;xor    al, al ; 26/04/2013       
  2435                              <1> ;1:
  2436                              <1> 		; tstb uquant / is the time quantum 0?
  2437                              <1> 		; bne 1f / no, don't swap it out
  2438                              <1> 
  2439                              <1> sysrele: ; < release >
  2440                              <1> 	; 14/10/2015
  2441                              <1> 	; 01/09/2015
  2442                              <1> 	; 24/07/2015
  2443                              <1> 	; 14/05/2015
  2444                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2445                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2446                              <1> 	;
  2447                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2448                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2449                              <1> 	; turns off the system flag. It then checked to see if there is
  2450                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2451                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2452                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2453                              <1> 	; the user, a rti is made.
  2454                              <1> 	;
  2455                              <1> 	; Calling sequence:
  2456                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2457                              <1> 	; Arguments:
  2458                              <1> 	;	-	
  2459                              <1> 	; ...............................................................
  2460                              <1> 	;	
  2461                              <1> 	; 23/02/2014 (swapret)
  2462                              <1> 	; 22/09/2013
  2463                              <1> sysrel0: ;1:
  2464 000032E9 803D[AC6D0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2465                              <1> 		; tstb uquant / is the time quantum 0?
  2466 000032F0 7705                <1>         ja      short swapret
  2467                              <1> 		; bne 1f / no, don't swap it out
  2468                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2469 000032F2 E80D140000          <1> 	call	tswap
  2470                              <1> 		; jsr r0,tswap / yes, swap it out
  2471                              <1> ;
  2472                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2473                              <1> swapret: ;1:
  2474                              <1> 	; 10/09/2015
  2475                              <1> 	; 01/09/2015
  2476                              <1> 	; 14/05/2015
  2477                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2478                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2479                              <1> 	; cli
  2480                              <1> 	; 24/07/2015
  2481                              <1> 	;
  2482                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2483                              <1> 	;; mov	esp, [u.usp]
  2484                              <1> 
  2485                              <1> 	; 22/09/2013
  2486 000032F7 E8DF150000          <1> 	call	isintr
  2487                              <1> 	; 20/10/2013
  2488 000032FC 7405                <1> 	jz	short sysrel1
  2489 000032FE E877000000          <1> 	call	intract
  2490                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2491                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2492                              <1> 		               ; / action
  2493                              <1> sysrel1:
  2494 00003303 FA                  <1> 	cli ; 14/10/2015
  2495 00003304 FE0D[586D0000]      <1> 	dec	byte [sysflg]
  2496                              <1> 		; decb sysflg / turn system flag off
  2497 0000330A A1[C46D0000]        <1> 	mov     eax, [u.pgdir]
  2498 0000330F 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2499                              <1> 			  ; (others are different than kernel page tables) 
  2500                              <1> 	; 10/09/2015
  2501 00003312 61                  <1> 	popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax
  2502                              <1> 		; mov (sp)+,sc / restore user registers
  2503                              <1> 		; mov (sp)+,mq
  2504                              <1> 		; mov (sp)+,ac
  2505                              <1> 		; mov (sp)+,r5
  2506                              <1> 		; mov (sp)+,r4
  2507                              <1> 		; mov (sp)+,r3
  2508                              <1> 		; mov (sp)+,r2
  2509                              <1> 	;
  2510 00003313 A1[646D0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2511 00003318 0FA9                <1> 	pop	gs
  2512 0000331A 0FA1                <1> 	pop	fs
  2513 0000331C 07                  <1> 	pop	es
  2514 0000331D 1F                  <1> 	pop	ds
  2515 0000331E CF                  <1> 	iretd	
  2516                              <1> 		; rti / no, return from interrupt
  2517                              <1> 
  2518                              <1> badsys:
  2519                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2520                              <1> 	; (Major Modification: 'core' dumping procedure in
  2521                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2522                              <1> 	;	has been changed to print 'Invalid System Call !'
  2523                              <1> 	;	message on the user's console tty.)
  2524                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2525                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2526                              <1> 	; (EAX = Function number)  
  2527                              <1> 	;
  2528 0000331F FE05[B46D0000]      <1> 	inc	byte [u.bsys]
  2529                              <1> 	;
  2530 00003325 8B1D[5C6D0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2531 0000332B 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2532 0000332D E89DE3FFFF          <1> 	call	dwordtohex
  2533 00003332 8915[88650000]      <1> 	mov	[bsys_msg_eip], edx
  2534 00003338 A3[8C650000]        <1> 	mov	[bsys_msg_eip+4], eax
  2535 0000333D A1[646D0000]        <1> 	mov	eax, [u.r0]
  2536 00003342 E888E3FFFF          <1> 	call	dwordtohex
  2537 00003347 8915[78650000]      <1> 	mov	[bsys_msg_eax], edx
  2538 0000334D A3[7C650000]        <1> 	mov	[bsys_msg_eax+4], eax
  2539                              <1> 	; 11/12/2021
  2540                              <1> 	;xor	eax, eax
  2541                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2542                              <1> 	;mov	ebx, [u.fofp]
  2543                              <1> 	;mov	[ebx], eax
  2544                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2545                              <1> 	;inc	eax
  2546                              <1> 	; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 
  2547                              <1> 	; (Retro UNIX 386 v1.2)
  2548                              <1> 	;mov	al, 8 ; /dev/tty inode number (runix v2 fs)
  2549                              <1> 	;; eax = 8 ; inode number of console tty (for user)	
  2550                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2551                              <1> 		; writei
  2552                              <1> 		; INPUTS ->
  2553                              <1> 		;    r1 - inode number
  2554                              <1> 		;    u.count - byte count to be written
  2555                              <1> 		;    u.base - points to user buffer
  2556                              <1> 		;    u.fofp - points to word with current file offset
  2557                              <1> 		; OUTPUTS ->
  2558                              <1> 		;    u.count - cleared
  2559                              <1> 		;    u.nread - accumulates total bytes passed back	
  2560                              <1> 		;
  2561                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2562                              <1> 	;call	writei
  2563                              <1> 	;;mov	eax, 1
  2564                              <1> 	;jmp	sysexit
  2565                              <1> 
  2566                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2567 00003352 BE[59650000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2568 00003357 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2569 0000335E 8A83[63690000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2570 00003364 C605[57680000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2571 0000336B A2[996D0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2572 00003370 E86D2B0000          <1> 	call	print_cmsg
  2573                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2574 00003375 E9F3FEFFFF          <1> 	jmp	error
  2575                              <1> 
  2576                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2577                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2578                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2579                              <1> 		; br 1f / error
  2580                              <1> 		; neg r1 / negate the i-number to open the core image file
  2581                              <1> 		       ; / for writing
  2582                              <1> 		; jsr r0,iopen / open the core image file
  2583                              <1> 		; jsr r0,itrunc / free all associated blocks
  2584                              <1> 		; br 2f
  2585                              <1> ;1:
  2586                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2587                              <1> 		; jsr r0,maknod / make an i-node
  2588                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2589                              <1> ;2:
  2590                              <1> 		; mov $core,u.base / move address core to u.base
  2591                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2592                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2593                              <1> 		; clr u.off / clear user offset
  2594                              <1> 		; jsr r0,writei / write out the core image to the user
  2595                              <1> 		; mov $user,u.base / pt. u.base to user
  2596                              <1> 		; mov $64.,u.count / u.count = 64
  2597                              <1> 		; jsr r0,writei / write out all the user parameters
  2598                              <1> 		; neg r1 / make i-number positive
  2599                              <1> 		; jsr r0,iclose / close the core image file
  2600                              <1> 		; br sysexit /
  2601                              <1> ;3:
  2602                              <1> 		; <core\0\0>
  2603                              <1> 
  2604                              <1> intract: ; / interrupt action
  2605                              <1> 	; 14/10/2015
  2606                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2607                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2608                              <1> 	;
  2609                              <1> 	; Retro UNIX 8086 v1 modification !
  2610                              <1> 	; (Process/task switching and quit routine by using
  2611                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2612                              <1> 	;
  2613                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2614                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2615                              <1> 	;		'intract' will jump to 'sysexit'.
  2616                              <1> 	;	    Intract will return to the caller 
  2617                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2618                              <1> 	; 14/10/2015
  2619 0000337A FB                  <1> 	sti
  2620                              <1> 	; 07/12/2013	
  2621 0000337B 66FF05[B26D0000]    <1> 	inc 	word [u.quit]
  2622 00003382 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2623 00003384 66FF0D[B26D0000]    <1> 	dec	word [u.quit]
  2624                              <1> 	; 16/04/2015
  2625 0000338B C3                  <1> 	retn
  2626                              <1> intrct0:	
  2627 0000338C 58                  <1> 	pop	eax ; call intract -> retn
  2628                              <1> 	;
  2629 0000338D 31C0                <1> 	xor 	eax, eax
  2630 0000338F FEC0                <1> 	inc	al  ; mov ax, 1
  2631                              <1> ;;;
  2632                              <1> 	; UNIX v1 original 'intract' routine... 
  2633                              <1> 	; / interrupt action
  2634                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2635                              <1> 		; bne 1f / no, 1f
  2636                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2637                              <1> 	; 1: / now in user area
  2638                              <1> 		; mov r1,-(sp) / save r1
  2639                              <1> 		; mov u.ttyp,r1 
  2640                              <1> 			; / pointer to tty buffer in control-to r1
  2641                              <1> 		; cmpb 6(r1),$177
  2642                              <1> 			; / is the interrupt char equal to "del"
  2643                              <1> 		; beq 1f / yes, 1f
  2644                              <1> 		; clrb 6(r1) 
  2645                              <1> 		        ; / no, clear the byte 
  2646                              <1> 			; / (must be a quit character)
  2647                              <1> 		; mov (sp)+,r1 / restore r1
  2648                              <1> 		; clr u.quit / clear quit flag
  2649                              <1> 		; bis $20,2(sp) 
  2650                              <1> 		    	; / set trace for quit (sets t bit of 
  2651                              <1> 			; / ps-trace trap)
  2652                              <1> 		; rti   ;  / return from interrupt
  2653                              <1> 	; 1: / interrupt char = del
  2654                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2655                              <1> 			   ; / in the buffer
  2656                              <1> 		; mov (sp)+,r1 / restore r1
  2657                              <1> 		; cmp u.intr,$core / should control be 
  2658                              <1> 				; / transferred to loc core?
  2659                              <1> 		; blo 1f
  2660                              <1> 		; jmp *u.intr / user to do rti yes, 
  2661                              <1> 				; / transfer to loc core
  2662                              <1> 	; 1:
  2663                              <1> 		; sys 1 / exit
  2664                              <1> 
  2665                              <1> sysexit: ; <terminate process>
  2666                              <1> 	; 30/11/2021 - etro UNIX 386 v1.2
  2667                              <1> 	; 01/09/2015
  2668                              <1> 	; 31/08/2015
  2669                              <1> 	; 14/05/2015
  2670                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2671                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2672                              <1> 	;
  2673                              <1> 	; 'sysexit' terminates a process. First each file that
  2674                              <1> 	; the process has opened is closed by 'flose'. The process
  2675                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2676                              <1> 	; searched to find children of the dying process. If any of
  2677                              <1> 	; children are zombies (died by not waited for), they are
  2678                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2679                              <1> 	; dying process's parent. When the parent is found, it is
  2680                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2681                              <1> 	; one of these, the dying process just dies. If it is waiting
  2682                              <1> 	; for a child process to die, it notified that it doesn't 
  2683                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2684                              <1> 	; (waiting to active). It is awakened and put on runq by
  2685                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2686                              <1> 	; it will never be run again but stays around until a 'wait'
  2687                              <1> 	; is completed by it's parent process. If the parent is not
  2688                              <1> 	; found, process just dies. This means 'swap' is called with
  2689                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2690                              <1> 	; to write out the process and 'rswap' reads the new process
  2691                              <1> 	; over the one that dies..i.e., the dying process is 
  2692                              <1> 	; overwritten and destroyed.	
  2693                              <1>  	;
  2694                              <1> 	; Calling sequence:
  2695                              <1> 	;	sysexit or conditional branch.
  2696                              <1> 	; Arguments:
  2697                              <1> 	;	-	
  2698                              <1> 	; ...............................................................
  2699                              <1> 	;	
  2700                              <1> 	; Retro UNIX 8086 v1 modification: 
  2701                              <1> 	;       System call number (=1) is in EAX register.
  2702                              <1> 	;
  2703                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2704                              <1> 	;       registers depending of function details.
  2705                              <1> 	;
  2706                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2707                              <1> 	;
  2708                              <1> ; / terminate process
  2709                              <1> 	; AX = 1
  2710                              <1> 	;dec 	ax ; 0
  2711                              <1> 	; 30/11/2021
  2712 00003391 48                  <1> 	dec	eax ; 0
  2713 00003392 66A3[B06D0000]      <1> 	mov	[u.intr], ax ; 0
  2714                              <1> 		; clr u.intr / clear interrupt control word
  2715                              <1> 		; clr r1 / clear r1
  2716                              <1> 	; AX = 0
  2717                              <1> sysexit_1: ; 1:
  2718                              <1> 	; AX = File descriptor
  2719                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2720                              <1> 		; / Search the whole list
  2721 00003398 E86A0D0000          <1> 	call	fclose
  2722                              <1> 		; jsr r0,fclose / close all files the process opened
  2723                              <1> 	;; ignore error return
  2724                              <1> 		; br .+2 / ignore error return
  2725                              <1> 	;inc	ax
  2726 0000339D FEC0                <1> 	inc	al
  2727                              <1> 		; inc r1 / increment file descriptor
  2728                              <1> 	;cmp	ax, 10
  2729 0000339F 3C0A                <1> 	cmp	al, 10
  2730                              <1> 		; cmp r1,$10. / end of u.fp list?
  2731 000033A1 72F5                <1> 	jb	short sysexit_1
  2732                              <1> 		; blt 1b / no, go back
  2733 000033A3 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2734                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2735 000033AA 88A3[83690000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2736                              <1> 		; clrb p.stat-1(r1) / free the process
  2737                              <1> 	;shl	bx, 1
  2738 000033B0 D0E3                <1> 	shl	bl, 1
  2739                              <1> 		; asl r1 / use r1 for index into the below tables
  2740 000033B2 668B8B[22690000]    <1> 	mov	cx, [ebx+p.pid-2]
  2741                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2742 000033B9 668B93[42690000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2743                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2744                              <1> 	; xor 	bx, bx ; 0
  2745 000033C0 30DB                <1> 	xor	bl, bl ; 0
  2746                              <1> 		; clr r2
  2747 000033C2 31F6                <1> 	xor	esi, esi ; 0
  2748                              <1> 		; clr r5 / initialize reg
  2749                              <1> sysexit_2: ; 1:
  2750                              <1> 	        ; / find children of this dying process, 
  2751                              <1> 		; / if they are zombies, free them
  2752                              <1> 	;add	bx, 2
  2753 000033C4 80C302              <1> 	add	bl, 2
  2754                              <1> 		; add $2,r2 / search parent process table 
  2755                              <1> 		          ; / for dying process's name
  2756 000033C7 66398B[42690000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2757                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2758 000033CE 7513                <1> 	jne	short sysexit_4
  2759                              <1> 		; bne 3f / no
  2760                              <1> 	;shr	bx, 1
  2761 000033D0 D0EB                <1> 	shr	bl, 1
  2762                              <1> 		; asr r2 / yes, it is a parent
  2763 000033D2 80BB[83690000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2764                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2765                              <1> 				     ; / dying process a zombie
  2766 000033D9 7506                <1> 	jne	short sysexit_3 
  2767                              <1> 		; bne 2f / no
  2768 000033DB 88A3[83690000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2769                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2770                              <1> sysexit_3: ; 2:
  2771                              <1> 	;shr	bx, 1
  2772 000033E1 D0E3                <1> 	shl	bl, 1
  2773                              <1> 		; asl r2
  2774                              <1> sysexit_4: ; 3:
  2775                              <1> 		; / search the process name table 
  2776                              <1> 		; / for the dying process's parent
  2777 000033E3 663993[22690000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2778                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2779 000033EA 7502                <1> 	jne	short sysexit_5
  2780                              <1> 		; bne 3f / no
  2781 000033EC 89DE                <1> 	mov	esi, ebx
  2782                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2783                              <1> 		          ; / process # x2) in r5
  2784                              <1> sysexit_5: ; 3:
  2785                              <1> 	;cmp	bx, nproc + nproc
  2786 000033EE 80FB20              <1> 	cmp	bl, nproc + nproc
  2787                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2788 000033F1 72D1                <1> 	jb	short sysexit_2
  2789                              <1> 		; blt 1b / no, go back
  2790                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2791 000033F3 21F6                <1> 	and	esi, esi ; r5=r1
  2792 000033F5 7431                <1> 	jz	short sysexit_6
  2793                              <1> 		; beq 2f / no parent has been found. 
  2794                              <1> 		       ; / The process just dies
  2795 000033F7 66D1EE              <1> 	shr	si, 1
  2796                              <1> 		; asr r1 / set up index to p.stat
  2797 000033FA 8A86[83690000]      <1> 	mov	al, [esi+p.stat-1]
  2798                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2799 00003400 20C0                <1> 	and	al, al
  2800 00003402 7424                <1> 	jz	short sysexit_6
  2801                              <1> 		; beq 2f / if its been freed, 2f
  2802 00003404 3C03                <1> 	cmp	al, 3
  2803                              <1> 		; cmp r2,$3 / is parent a zombie?
  2804 00003406 7420                <1> 	je	short sysexit_6
  2805                              <1> 		; beq 2f / yes, 2f
  2806                              <1> 	; BH = 0
  2807 00003408 8A1D[B56D0000]      <1> 	mov	bl, [u.uno]
  2808                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2809 0000340E C683[83690000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2810                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2811                              <1> 	; 05/02/2014
  2812 00003415 3C01                <1> 	cmp	al, 1 ; SRUN
  2813 00003417 740F                <1> 	je	short sysexit_6
  2814                              <1> 	;cmp	al, 2
  2815                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2816                              <1> 			  ; / this child to die
  2817                              <1> 	;jne	short sysexit_6	
  2818                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2819                              <1> 	; 05/02/2014
  2820                              <1> 	; p.stat = 2 --> waiting
  2821                              <1> 	; p.stat = 4 --> sleeping
  2822 00003419 C686[83690000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2823                              <1> 	;dec	byte [esi+p.stat-1]
  2824                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2825 00003420 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2826                              <1> 	; 
  2827                              <1> 	;mov	ebx, runq + 4
  2828                              <1> 		; mov $runq+4,r2 / on the runq
  2829 00003423 E8B3130000          <1> 	call	putlu
  2830                              <1> 		; jsr r0, putlu
  2831                              <1> sysexit_6: ; 2:
  2832                              <1> 	; 31/08/2015
  2833                              <1> 		; / the process dies
  2834 00003428 C605[B56D0000]00    <1> 	mov	byte [u.uno], 0
  2835                              <1> 		; clrb u.uno / put zero as the process number, 
  2836                              <1> 	           ; / so "swap" will
  2837 0000342F E8DA120000          <1> 	call	swap
  2838                              <1> 		; jsr r0,swap / overwrite process with another process
  2839                              <1> hlt_sys:
  2840                              <1> 	;sti ; 18/01/2014
  2841                              <1> hlts0:
  2842 00003434 F4                  <1> 	hlt
  2843 00003435 EBFD                <1> 	jmp	short hlts0
  2844                              <1> 		; 0 / and thereby kill it; halt?
  2845                              <1> 
  2846                              <1> syswait: ; < wait for a processs to die >
  2847                              <1> 	; 09/02/2022
  2848                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2849                              <1> 	; 17/09/2015
  2850                              <1> 	; 02/09/2015
  2851                              <1> 	; 01/09/2015
  2852                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2853                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2854                              <1> 	;
  2855                              <1> 	; 'syswait' waits for a process die. 
  2856                              <1> 	; It works in following way:
  2857                              <1> 	;    1) From the parent process number, the parent's 
  2858                              <1> 	; 	process name is found. The p.ppid table of parent
  2859                              <1> 	;	names is then searched for this process name.
  2860                              <1> 	;	If a match occurs, r2 contains child's process
  2861                              <1> 	;	number. The child status is checked to see if it is
  2862                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2863                              <1> 	;	If it is, the child process is freed and it's name
  2864                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2865                              <1> 	;	If the child is not a zombie, nothing happens and
  2866                              <1> 	;	the search goes on through the p.ppid table until
  2867                              <1> 	;	all processes are checked or a zombie is found.
  2868                              <1> 	;    2) If no zombies are found, a check is made to see if
  2869                              <1> 	;	there are any children at all. If there are none,
  2870                              <1> 	;	an error return is made. If there are, the parent's
  2871                              <1> 	;	status is set to 2 (waiting for child to die),
  2872                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2873                              <1> 	;	is made to wait on the next process.
  2874                              <1> 	;
  2875                              <1> 	; Calling sequence:
  2876                              <1> 	;	?
  2877                              <1> 	; Arguments:
  2878                              <1> 	;	-
  2879                              <1> 	; Inputs: - 
  2880                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2881                              <1> 	; ...............................................................
  2882                              <1> 	;				
  2883                              <1> 	
  2884                              <1> ; / wait for a process to die
  2885                              <1> 
  2886                              <1> syswait_0:
  2887 00003437 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2888                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2889 0000343E D0E3                <1> 	shl	bl, 1
  2890                              <1> 	;shl	bx, 1
  2891                              <1> 		; asl r1 / x2 to get index into p.pid table
  2892 00003440 668B83[22690000]    <1> 	mov	ax, [ebx+p.pid-2]
  2893                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2894 00003447 31F6                <1> 	xor	esi, esi
  2895                              <1> 		; clr r2
  2896 00003449 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2897                              <1> 	;xor 	cl, cl
  2898                              <1> 		; clr r3 / initialize reg 3
  2899                              <1> syswait_1: ; 1:
  2900                              <1> 	; 09/02/2022
  2901 0000344B 46                  <1> 	inc	esi
  2902 0000344C 46                  <1> 	inc	esi
  2903                              <1> 	;add	si, 2
  2904                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2905                              <1> 			  ; / search table of parent processes 
  2906                              <1> 			  ; / for this process name
  2907 0000344D 663B86[42690000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2908                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2909                              <1> 			            ; / process number
  2910 00003454 7531                <1> 	jne	short syswait_3
  2911                              <1> 		; bne 3f / branch if no match of parent process name
  2912                              <1> 	;inc	cx
  2913 00003456 FEC1                <1> 	inc	cl
  2914                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2915                              <1> 	; 09/02/2022
  2916 00003458 D1EE                <1> 	shr	esi, 1
  2917                              <1> 	;shr	si, 1
  2918                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2919                              <1> 	; The possible states ('p.stat' values) of a process are:
  2920                              <1> 	;	0 = free or unused
  2921                              <1> 	;	1 = active
  2922                              <1> 	;	2 = waiting for a child process to die
  2923                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2924 0000345A 80BE[83690000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2925                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2926 00003461 7522                <1> 	jne	short syswait_2
  2927                              <1> 		; bne 2f / no, skip it
  2928 00003463 88BE[83690000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2929                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2930                              <1> 	; 09/02/2022
  2931 00003469 D1E6                <1> 	shl	esi, 1
  2932                              <1> 	;shl	si, 1
  2933                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2934 0000346B 0FB786[22690000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2935 00003472 A3[646D0000]        <1> 	mov	[u.r0], eax
  2936                              <1> 		; mov p.pid-2(r2),*u.r0 
  2937                              <1> 			      ; / put childs process name in (u.r0)
  2938                              <1> 	;
  2939                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2940                              <1> 	;
  2941                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2942                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2943                              <1> 	; system call loop from the application/program if it calls
  2944                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2945                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2946                              <1> 	;
  2947                              <1> 	; Note: syswait will return with error if there is not a
  2948                              <1> 	;       zombie or running process to wait.	
  2949                              <1> 	;
  2950                              <1> 	;sub	ax, ax
  2951                              <1> 	; 08/01/2022
  2952 00003477 29C0                <1> 	sub	eax, eax
  2953 00003479 668986[42690000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2954 00003480 E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2955                              <1> 	;
  2956                              <1> 	;jmp	sysret
  2957                              <1> 		; br sysret1 / return cause child is dead
  2958                              <1> syswait_2: ; 2:
  2959                              <1> 	; 09/02/2022
  2960 00003485 D1E6                <1> 	shl	esi, 1
  2961                              <1> 	;shl	si, 1
  2962                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2963                              <1> syswait_3: ; 3:
  2964 00003487 6683FE20            <1> 	cmp	si, nproc+nproc
  2965                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2966 0000348B 72BE                <1> 	jb	short syswait_1
  2967                              <1> 		; blt 1b / no, continue search
  2968                              <1> 	;and	cx, cx
  2969 0000348D 20C9                <1> 	and	cl, cl
  2970                              <1> 		; tst r3 / one gets here if there are no children 
  2971                              <1> 		       ; / or children that are still active
  2972                              <1> 	; 30/10/2013
  2973 0000348F 7515                <1> 	jnz	short syswait_4
  2974                              <1> 	;jz	error
  2975                              <1> 		; beq error1 / there are no children, error
  2976 00003491 890D[646D0000]      <1> 	mov	[u.r0], ecx ; 0
  2977                              <1> 	; 09/02/2022
  2978 00003497 C705[D86D0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2978 0000349F 0000                <1>
  2979                              <1> 			; miscellaneous/other errors
  2980 000034A1 E9C7FDFFFF          <1> 	jmp	error
  2981                              <1> syswait_4:
  2982 000034A6 8A1D[B56D0000]      <1> 	mov	bl, [u.uno]
  2983                              <1> 		; movb u.uno,r1 / there are children so put 
  2984                              <1> 			      ; / parent process number in r1
  2985 000034AC FE83[83690000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2986                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2987                              <1> 				  ; / other children to die
  2988                              <1> 	; 04/11/2013
  2989 000034B2 E857120000          <1> 	call	swap
  2990                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2991 000034B7 E97BFFFFFF          <1> 	jmp	syswait_0
  2992                              <1> 		; br syswait / wait on next process
  2993                              <1> 
  2994                              <1> sysfork: ; < create a new process >
  2995                              <1> 	; 27/02/2022
  2996                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2997                              <1> 	; 18/09/2015
  2998                              <1> 	; 04/09/2015
  2999                              <1> 	; 02/09/2015
  3000                              <1> 	; 01/09/2015
  3001                              <1> 	; 28/08/2015
  3002                              <1> 	; 14/05/2015
  3003                              <1> 	; 10/05/2015
  3004                              <1> 	; 09/05/2015
  3005                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3006                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3007                              <1> 	;
  3008                              <1> 	; 'sysfork' creates a new process. This process is referred
  3009                              <1> 	; to as the child process. This new process core image is
  3010                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3011                              <1> 	; distinction is the return location and the fact that (u.r0)
  3012                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3013                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3014                              <1> 	; 'sysfork' works in the following manner: 	
  3015                              <1> 	;    1) The process status table (p.stat) is searched to find
  3016                              <1> 	;	a process number that is unused. If none are found
  3017                              <1> 	;	an error occurs.
  3018                              <1> 	;    2) when one is found, it becomes the child process number
  3019                              <1> 	;	and it's status (p.stat) is set to active.
  3020                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3021                              <1> 	;	character in that tty buffer is cleared.
  3022                              <1> 	;    4) The child process is put on the lowest priority run 
  3023                              <1> 	;	queue via 'putlu'.
  3024                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3025                              <1> 	;	it is a unique number) and is put in the child's unique
  3026                              <1> 	;	identifier; process id (p.pid).
  3027                              <1> 	;    6) The process name of the parent is then obtained and
  3028                              <1> 	;	placed in the unique identifier of the parent process
  3029                              <1> 	;	name is then put in 'u.r0'.	
  3030                              <1> 	;    7) The child process is then written out on disk by
  3031                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3032                              <1> 	;	and the child is born. (The child process is written 
  3033                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3034                              <1> 	;	number.)
  3035                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3036                              <1> 	;    9) The child process name is put in 'u.r0'.
  3037                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3038                              <1> 	;	create the return address for the parent process.
  3039                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3040                              <1> 	;	the parent has opened. For each file the parent has
  3041                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3042                              <1> 	;	to indicate that the child process also has opened
  3043                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3044                              <1> 	;
  3045                              <1> 	; Calling sequence:
  3046                              <1> 	;	from shell ?
  3047                              <1> 	; Arguments:
  3048                              <1> 	;	-
  3049                              <1> 	; Inputs: -
  3050                              <1> 	; Outputs: *u.r0 - child process name
  3051                              <1> 	; ...............................................................
  3052                              <1> 	;	
  3053                              <1> 	; Retro UNIX 8086 v1 modification: 
  3054                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3055                              <1> 	;	= process id of child a parent process returns
  3056                              <1> 	;	= process id of parent when a child process returns
  3057                              <1> 	;
  3058                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3059                              <1> 	;	in following manner: (with an example: c library, fork)
  3060                              <1> 	;	
  3061                              <1> 	;	1:
  3062                              <1> 	;		sys	fork
  3063                              <1> 	;			br 1f  / child process returns here
  3064                              <1> 	;		bes	2f     / parent process returns here
  3065                              <1> 	;		/ pid of new process in r0
  3066                              <1> 	;		rts	pc
  3067                              <1> 	;	2: / parent process condionally branches here
  3068                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3069                              <1> 	;		rts	pc
  3070                              <1> 	;
  3071                              <1> 	;	1: / child process brances here
  3072                              <1> 	;		clr	r0   / pid = 0 in child process
  3073                              <1> 	;		rts	pc
  3074                              <1> 	;
  3075                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3076                              <1> 	;		// pid = fork();
  3077                              <1> 	;		//
  3078                              <1> 	;		// pid == 0 in child process; 
  3079                              <1> 	;		// pid == -1 means error return
  3080                              <1> 	;		// in child, 
  3081                              <1> 	;		//	parents id is in par_uid if needed
  3082                              <1> 	;		
  3083                              <1> 	;		_fork:
  3084                              <1> 	;			mov	$.fork,eax
  3085                              <1> 	;			int	$0x30
  3086                              <1> 	;			jmp	1f
  3087                              <1> 	;			jnc	2f
  3088                              <1> 	;			jmp	cerror
  3089                              <1> 	;		1:
  3090                              <1> 	;			mov	eax,_par_uid
  3091                              <1> 	;			xor	eax,eax
  3092                              <1> 	;		2:
  3093                              <1> 	;			ret
  3094                              <1> 	;
  3095                              <1> 	;	In Retro UNIX 8086 v1,
  3096                              <1> 	;	'sysfork' returns in following manner:
  3097                              <1> 	;	
  3098                              <1> 	;		mov	ax, sys_fork
  3099                              <1> 	;		mov	bx, offset @f ; routine for child
  3100                              <1> 	;		int	20h
  3101                              <1> 	;		jc	error
  3102                              <1> 	;		
  3103                              <1> 	;	; Routine for parent process here (just after 'jc')
  3104                              <1> 	;		mov	word ptr [pid_of_child], ax
  3105                              <1> 	;		jmp	next_routine_for_parent	
  3106                              <1> 	;
  3107                              <1> 	;	@@: ; routine for child process here				
  3108                              <1> 	;		....	
  3109                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3110                              <1> 	;	       for child process by using BX input.
  3111                              <1> 	;	      (at first, parent process will return then 
  3112                              <1> 	;	      child process will return -after swapped in-
  3113                              <1> 	;	      'syswait' is needed in parent process
  3114                              <1> 	;	      if return from child process will be waited for.)
  3115                              <1> 	;	  				
  3116                              <1> 	
  3117                              <1> ; / create a new process
  3118                              <1> 	; EBX = return address for child process 
  3119                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3120 000034BC 31F6                <1> 	xor 	esi, esi
  3121                              <1> 		; clr r1
  3122                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3123 000034BE 46                  <1> 	inc	esi
  3124                              <1> 		; inc r1
  3125 000034BF 80BE[83690000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3126                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3127 000034C6 760B                <1> 	jna	short sysfork_2	
  3128                              <1> 		; beq 1f / it's unused so branch
  3129 000034C8 6683FE10            <1> 	cmp	si, nproc
  3130                              <1> 		; cmp r1,$nproc / all processes checked
  3131 000034CC 72F0                <1> 	jb	short sysfork_1
  3132                              <1> 		; blt 1b / no, branch back
  3133                              <1> 	;
  3134                              <1> 	; Retro UNIX 8086 v1. modification:
  3135                              <1> 	;	Parent process returns from 'sysfork' to address 
  3136                              <1> 	;	which is just after 'sysfork' system call in parent
  3137                              <1> 	;	process. Child process returns to address which is put
  3138                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3139                              <1> 	;
  3140                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3141                              <1> 		             ; / to old process return
  3142                              <1> 		; br error1 / no room for a new process
  3143                              <1> sysfork_0:
  3144 000034CE E99AFDFFFF          <1> 	jmp	error
  3145                              <1> sysfork_2: ; 1:
  3146 000034D3 E80CF0FFFF          <1> 	call	allocate_page
  3147                              <1> 	;jc	error
  3148                              <1> 	; 08/01/2022
  3149 000034D8 72F4                <1> 	jc	short sysfork_0
  3150                              <1> 
  3151 000034DA 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3152                              <1> 	; Retro UNIX 386 v1 modification!
  3153 000034DB E8FDF1FFFF          <1> 	call	duplicate_page_dir
  3154                              <1> 		; EAX = New page directory 
  3155 000034E0 7308                <1> 	jnc	short sysfork_3
  3156 000034E2 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3157 000034E3 E8C4F1FFFF          <1> 	call 	deallocate_page
  3158                              <1> 	;jmp	error
  3159                              <1> 	; 08/01/2022
  3160 000034E8 EBE4                <1> 	jmp	short sysfork_0  ; error
  3161                              <1> sysfork_3:
  3162                              <1> 	; Retro UNIX 386 v1 modification !
  3163 000034EA 56                  <1> 	push	esi
  3164 000034EB E895120000          <1> 	call	wswap ; save current user (u) structure, user registers
  3165                              <1> 		      ; and interrupt return components (for IRET)
  3166 000034F0 8705[C46D0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3167 000034F6 A3[C86D0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3168 000034FB 5E                  <1> 	pop	esi
  3169 000034FC 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3170                              <1> 		; [u.usp] = esp
  3171 000034FD 89F7                <1> 	mov	edi, esi
  3172                              <1> 	;shl	di, 2
  3173                              <1> 	; 08/01/2022
  3174 000034FF C1E702              <1> 	shl	edi, 2
  3175 00003502 8987[90690000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3176 00003508 A3[C06D0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3177                              <1> 	; 28/08/2015
  3178 0000350D 0FB605[B56D0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3179                              <1> 		; movb u.uno,-(sp) / save parent process number
  3180 00003514 89C7                <1> 	mov	edi, eax
  3181 00003516 50                  <1>         push	eax ; ** 
  3182 00003517 8A87[63690000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3183                              <1> 	; 18/09/2015 (27/02/2022)
  3184 0000351D 8886[63690000]      <1> 	mov	[esi+p.ttyc-1], al ; set child's console tty
  3185                              <1> 	; 27/02/2022 (p.waitc is not used)
  3186                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3187                              <1> 	; 27/02/2022 (BugFix)
  3188                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3189                              <1> 	;			   ; ah - reset child's wait channel
  3190 00003523 89F0                <1> 	mov	eax, esi
  3191 00003525 A2[B56D0000]        <1> 	mov	[u.uno], al ; child process number
  3192                              <1> 		;movb r1,u.uno / set child process number to r1
  3193 0000352A FE86[83690000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3194                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3195                              <1> 				; / process to active status
  3196                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3197                              <1> 			      ; / control tty buffer in r2
  3198                              <1>                 ; beq 2f / branch, if no such tty assigned
  3199                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3200                              <1> 	; 2:
  3201 00003530 53                  <1> 	push	ebx  ; * return address for the child process
  3202                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3203                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3204                              <1> 		; mov $runq+4,r2
  3205 00003531 E8A5120000          <1> 	call	putlu 
  3206                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3207                              <1> 			   ; / run queue
  3208                              <1> 	; 08/01/2022
  3209 00003536 D1E6                <1> 	shl	esi, 1
  3210                              <1> 	;shl	si, 1
  3211                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3212                              <1> 		       ; / into p.pid table
  3213 00003538 66FF05[446D0000]    <1> 	inc	word [mpid]
  3214                              <1> 		; inc mpid / increment m.pid; get a new process name
  3215 0000353F 66A1[446D0000]      <1> 	mov	ax, [mpid]
  3216 00003545 668986[22690000]    <1> 	mov	[esi+p.pid-2], ax
  3217                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3218                              <1> 				    ; / in child process' name slot
  3219 0000354C 5A                  <1> 	pop	edx  ; * return address for the child process
  3220                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3221 0000354D 5B                  <1>   	pop	ebx  ; **
  3222                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3223                              <1> 		; movb (sp),r2 / put parent process number in r2
  3224                              <1> 	; 08/01/2022
  3225 0000354E D1E3                <1> 	shl	ebx, 1
  3226                              <1> 	;shl 	bx, 1
  3227                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3228                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3229 00003550 668B83[22690000]    <1> 	mov	ax, [ebx+p.pid-2]
  3230                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3231                              <1> 				   ; / process
  3232 00003557 668986[42690000]    <1> 	mov	[esi+p.ppid-2], ax
  3233                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3234                              <1> 			  ; / in parent process slot for child
  3235 0000355E A3[646D0000]        <1> 	mov	[u.r0], eax	
  3236                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3237                              <1> 			     ; / at location where r0 was saved
  3238 00003563 8B2D[5C6D0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3239 00003569 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3240                              <1> 			   ; * return address for the child process
  3241                              <1> 		; mov $sysret1,-(sp) /
  3242                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3243                              <1> 			      ; / user is swapped out
  3244                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3245                              <1> 	; 04/09/2015 - 01/09/2015
  3246                              <1> 	; [u.usp] = esp
  3247 0000356C 68[8D320000]        <1> 	push	sysret ; ***
  3248 00003571 8925[606D0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3249                              <1> 			     ; (for child process)	
  3250 00003577 31C0                <1> 	xor 	eax, eax
  3251 00003579 66A3[9A6D0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3252                              <1> 	;
  3253 0000357F E801120000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3254                              <1> 		;jsr r0,wswap / put child process out on drum
  3255                              <1> 		;jsr r0,unpack / unpack user stack
  3256                              <1> 		;mov u.usp,sp / restore user stack pointer
  3257                              <1> 		; tst (sp)+ / bump stack pointer
  3258                              <1> 	; Retro UNIX 386 v1 modification !
  3259 00003584 58                  <1> 	pop	eax ; ***
  3260                              <1> 	; 08/01/2022
  3261 00003585 D1E3                <1> 	shl	ebx, 1
  3262                              <1> 	;shl 	bx, 1
  3263 00003587 8B83[90690000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3264 0000358D E81C120000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3265                              <1> 		      ; registers and return address (for IRET)
  3266                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3267 00003592 0FB705[446D0000]    <1>         movzx   eax, word [mpid]
  3268 00003599 A3[646D0000]        <1> 	mov	[u.r0], eax
  3269                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3270                              <1> 			       ; / where r0 was saved
  3271                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3272                              <1> 			          ; / process return
  3273                              <1> 	;xor	ebx, ebx
  3274 0000359E 31F6                <1> 	xor     esi, esi
  3275                              <1> 		;clr r1
  3276                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3277                              <1> 	      ; / opened by the parent process
  3278                              <1> 	; 08/01/2022
  3279                              <1> 	; 01/09/2015
  3280 000035A0 30FF                <1> 	xor	bh, bh
  3281 000035A2 8A9E[6E6D0000]      <1> 	mov 	bl, [esi+u.fp]
  3282                              <1> 	; 08/01/2022
  3283                              <1> 	;mov 	al, [esi+u.fp]
  3284                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3285 000035A8 08DB                <1> 	or	bl, bl
  3286                              <1> 	; 08/01/2022
  3287                              <1> 	;or	al, al
  3288 000035AA 7409                <1> 	jz	short sysfork_5	
  3289                              <1> 		; beq 2f / file has not been opened by parent, 
  3290                              <1> 		       ; / so branch
  3291                              <1> 	;mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3292                              <1> 	; 08/01/2022
  3293                              <1> 	;mov	ah, 16 ; Retro UNIX 386 v2 fsp structure size = 16 bytes
  3294                              <1> 	;mul	ah
  3295                              <1> 	;;movzx	ebx, ax
  3296                              <1> 	;mov	bx, ax
  3297                              <1> 	;mov	ebx, eax ; 08/01/2022
  3298                              <1> 	;shl	bx, 3
  3299                              <1> 		; asl r2 / multiply by 8
  3300                              <1>        		; asl r2 / to get index into fsp table
  3301                              <1>        		; asl r2
  3302                              <1> 	; 08/01/2022
  3303 000035AC C1E304              <1> 	shl	ebx, 4 ; multiply by 16
  3304                              <1> 	; 08/01/2022
  3305 000035AF FE83[CA690000]      <1> 	inc	byte [ebx+fsp-10] ; Retro UNIX 386 v2 fs fsp structure
  3306                              <1>   	;inc	byte [ebx+fsp-2]
  3307                              <1> 		; incb fsp-2(r2) / increment number of processes
  3308                              <1> 			     ; / using file, because child will now be
  3309                              <1> 			     ; / using this file
  3310                              <1> sysfork_5: ; 2:
  3311 000035B5 46                  <1>         inc     esi
  3312                              <1> 		; inc r1 / get next open file
  3313 000035B6 6683FE0A            <1>         cmp     si, 10
  3314                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3315                              <1> 			  ; / can be opened
  3316 000035BA 72E4                <1> 	jb	short sysfork_4	
  3317                              <1> 		; blt 1b / check next entry
  3318 000035BC E9CCFCFFFF          <1> 	jmp	sysret
  3319                              <1> 		; br sysret1
  3320                              <1> 
  3321                              <1> sysread: ; < read from file >
  3322                              <1> 	; 24/12/2021
  3323                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3324                              <1> 	; 27/03/2020
  3325                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3326                              <1> 	; 13/05/2015
  3327                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3328                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3329                              <1> 	;
  3330                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3331                              <1> 	; characters to be read. If finds the file from the file
  3332                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3333                              <1> 	; is returned from a successful open call (sysopen).
  3334                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3335                              <1> 	; is read into core via 'readi'.
  3336                              <1> 	;
  3337                              <1> 	; Calling sequence:
  3338                              <1> 	;	sysread; buffer; nchars
  3339                              <1> 	; Arguments:
  3340                              <1> 	;	buffer - location of contiguous bytes where 
  3341                              <1> 	;		 input will be placed.
  3342                              <1> 	;	nchars - number of bytes or characters to be read.
  3343                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3344                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3345                              <1> 	; ...............................................................
  3346                              <1> 	;				
  3347                              <1> 	; Retro UNIX 8086 v1 modification: 
  3348                              <1> 	;       'sysread' system call has three arguments; so,
  3349                              <1> 	;	* 1st argument, file descriptor is in BX register
  3350                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3351                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3352                              <1> 	;
  3353                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3354                              <1> 	;	to the user with number of bytes read. 
  3355                              <1> 	;
  3356                              <1> 
  3357 000035C1 E839000000          <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>        	; 04/12/2021
  3361 000035C6 7209                <1> 	jc	short sysread_err
  3362 000035C8 7529                <1> 	jnz	short rw3 ; error ! (permission denied)
  3363                              <1> 	;		; read a file while it is open for write!
  3364                              <1> 
  3365                              <1> 	; eax = inode number
  3366                              <1> 
  3367                              <1> 	; 04/12/2021
  3368                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3369                              <1> 	;test	ah, 80h
  3370                              <1> 	;	; tst r1 / negative i-number?
  3371                              <1> 	;;jnz	error
  3372                              <1> 	;;	; ble error1 / yes, error 1 to read
  3373                              <1> 	;;		   ; / it should be positive
  3374                              <1> 	;; 04/12/2021
  3375                              <1> 	;jnz	short sysread_err
  3376                              <1> 
  3377 000035CA E8221A0000          <1> 	call	readi
  3378                              <1> 		; jsr r0,readi / read data into core
  3379 000035CF EB13                <1> 	jmp	short rw0
  3380                              <1> 		; br 1f
  3381                              <1> sysread_err:
  3382                              <1> syswrite_err:
  3383                              <1> 	; 04/12/2021
  3384 000035D1 E997FCFFFF          <1> 	jmp	error
  3385                              <1> 
  3386                              <1> syswrite: ; < write to file >
  3387                              <1> 	; 24/12/2021
  3388                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3389                              <1> 	; 27/03/2020
  3390                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3391                              <1> 	; 13/05/2015
  3392                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3393                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3394                              <1> 	;
  3395                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3396                              <1> 	; and the number of characters to write. If finds the file
  3397                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3398                              <1> 	; descriptor is returned from a successful open or create call
  3399                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3400                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3401                              <1> 	;
  3402                              <1> 	; Calling sequence:
  3403                              <1> 	;	syswrite; buffer; nchars
  3404                              <1> 	; Arguments:
  3405                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3406                              <1> 	;	nchars - number of characters to be written.
  3407                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3408                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3409                              <1> 	; ...............................................................
  3410                              <1> 	;				
  3411                              <1> 	; Retro UNIX 8086 v1 modification: 
  3412                              <1> 	;       'syswrite' system call has three arguments; so,
  3413                              <1> 	;	* 1st argument, file descriptor is in BX register
  3414                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3415                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3416                              <1> 	;
  3417                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3418                              <1> 	;	to the user with number of bytes written. 
  3419                              <1> 	;
  3420                              <1> 
  3421 000035D6 E824000000          <1> 	call	rw1
  3422                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3423                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3424                              <1>        	; 04/12/2021
  3425 000035DB 72F4                <1> 	jc	short syswrite_err
  3426 000035DD 7414                <1> 	jz	short rw3 ; error ! (permission denied)
  3427                              <1> 			; write to a file while it is open for read
  3428                              <1> 	; eax = inode number
  3429                              <1> 	
  3430                              <1> 	; 04/12/2021
  3431                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3432                              <1> 	;test	ah, 80h
  3433                              <1> 	;	; tst r1 / positive i-number ?
  3434                              <1>         ;jz	short rw3 ; 13/05/2015
  3435                              <1> 	;;jz	error
  3436                              <1> 	;	; bge error1 / yes, error 1 
  3437                              <1> 	;		   ; / negative i-number means write
  3438                              <1>         ;neg	ax
  3439                              <1> 	;	; neg r1 / make it positive
  3440                              <1> 	
  3441 000035DF E81D1C0000          <1> 	call	writei
  3442                              <1>         	; jsr r0,writei / write data
  3443                              <1> rw0: ; 1:
  3444 000035E4 A1[906D0000]        <1>         mov	eax, [u.nread]
  3445 000035E9 A3[646D0000]        <1> 	mov	[u.r0], eax
  3446                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3447                              <1> 				  ; / into (u.r0)
  3448 000035EE E99AFCFFFF          <1> 	jmp	sysret
  3449                              <1>         	; br sysret1
  3450                              <1> rw3: 
  3451                              <1> 	; 13/05/2015
  3452 000035F3 C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3452 000035FB 0000                <1>
  3453                              <1> 	;stc
  3454                              <1> 	;retn
  3455                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.2
  3456 000035FD EBD2                <1> 	jmp	short syswrite_err
  3457                              <1> 
  3458                              <1> rw1:	
  3459                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3460                              <1> 	; 27/03/2020
  3461                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3462                              <1> 	; 14/05/2015
  3463                              <1> 	; 13/05/2015
  3464                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3465                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3466                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3467                              <1> 	;
  3468                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3469                              <1> 				;(in the user's virtual memory space)
  3470                              <1> 	;mov	[u.count], edx 
  3471                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3472                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3473                              <1> 	;;mov	eax, ebx ; file descriptor
  3474                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3475                              <1> 		             ; / (index to u.fp table) in r1
  3476                              <1> 	; 13/05/2015
  3477 000035FF C705[646D0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3477 00003607 0000                <1>
  3478                              <1> 	;
  3479                              <1> 	;; call	getf
  3480                              <1>         ; ebx = File descriptor
  3481 00003609 E8410B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3482                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3483                              <1> 	; AX = I-number of the file ; negative i-number means write
  3484                              <1> 
  3485                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3486                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3487                              <1> 	; BL = open mode & status flag (0 = read, 1 = write)
  3488                              <1> 	; eax = inode number (ax)
  3489                              <1> 	; 27/03/2020
  3490                              <1> 	; [cdev] = logical drive number 	
  3491                              <1> 
  3492                              <1> 	; 13/05/2015
  3493 0000360E 6683F801            <1> 	cmp 	ax, 1
  3494 00003612 721A                <1> 	jb	short rw2
  3495                              <1> 	;
  3496 00003614 890D[886D0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3497                              <1> 				;(in the user's virtual memory space)
  3498 0000361A 8915[8C6D0000]      <1> 	mov	[u.count], edx 
  3499                              <1> 	; 14/05/2015
  3500 00003620 C705[D86D0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3500 00003628 0000                <1>
  3501                              <1> 
  3502                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3503                              <1> 	; 27/03/2020 - Retro UNIX 386 v2
  3504 0000362A 80E301              <1> 	and	bl, 1
  3505                              <1> 		; zf = 0 -> open for write	
  3506                              <1> 		; zf = 1 -> open for read
  3507 0000362D C3                  <1> 	retn
  3508                              <1>         	; rts r0
  3509                              <1> rw2:
  3510                              <1> 	; 13/05/2015
  3511 0000362E C705[D86D0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3511 00003636 0000                <1>
  3512 00003638 C3                  <1> 	retn
  3513                              <1> 
  3514                              <1> 	; 18/04/2022
  3515                              <1> 	; 08/01/2022
  3516                              <1> 	; 02/01/2022
  3517                              <1> 	; 01/01/2022
  3518                              <1> 	; 27/12/2021
  3519                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code
  3520                              <1> sysopen: ;<open file>
  3521                              <1> 	; 04/12/2021
  3522                              <1> 	; 07/08/2020 (Retro UNIX 386 v2)
  3523                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3524                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3525                              <1> 	;
  3526                              <1> 	; 'sysopen' opens a file in following manner:
  3527                              <1> 	;    1) The second argument in a sysopen says whether to
  3528                              <1> 	;	open the file ro read (0) or write (>0).
  3529                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3530                              <1> 	;    3) The file is opened by 'iopen'.
  3531                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3532                              <1> 	;	and the user's open file list - u.fp.
  3533                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3534                              <1> 	;	b) An entry for the file is created in the fsp table.
  3535                              <1> 	;	c) The number of this entry is put on u.fp list.
  3536                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3537                              <1> 	;	   to by u.r0.
  3538                              <1> 	;
  3539                              <1> 	; Calling sequence:
  3540                              <1> 	;	sysopen; name; mode
  3541                              <1> 	; Arguments:
  3542                              <1> 	;	name - file name or path name
  3543                              <1> 	;	mode - 0 to open for reading
  3544                              <1> 	;	       1 to open for writing
  3545                              <1> 	; Inputs: (arguments)
  3546                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3547                              <1> 	;		  is put into r0's location on the stack.	
  3548                              <1> 	; ...............................................................
  3549                              <1> 	;				
  3550                              <1> 	; Retro UNIX 8086 v1 modification: 
  3551                              <1> 	;       'sysopen' system call has two arguments; so,
  3552                              <1> 	;	* 1st argument, name is pointed to by BX register
  3553                              <1> 	;	* 2nd argument, mode is in CX register
  3554                              <1> 	;
  3555                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3556                              <1> 	;	to the user with the file descriptor/number 
  3557                              <1> 	;	(index to u.fp list).
  3558                              <1> 	;
  3559                              <1> 	;call	arg2
  3560                              <1> 	; * name - 'u.namep' points to address of file/path name
  3561                              <1> 	;          in the user's program segment ('u.segmnt')
  3562                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3563                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3564                              <1> 	;          which is on top of stack.
  3565                              <1> 	;
  3566                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3567                              <1> 	;
  3568                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3569                              <1> 
  3570 00003639 891D[806D0000]      <1> 	mov	[u.namep], ebx
  3571 0000363F 51                  <1> 	push	ecx ; * ; 04/12/2021 (cx -> ecx)
  3572 00003640 E8400B0000          <1> 	call	namei
  3573                              <1> 		; jsr r0,namei / i-number of file in r1
  3574                              <1>      	;and	ax, ax
  3575                              <1> 	;jz	error ; File not found
  3576 00003645 722B                <1> 	jc	short fnotfound ; 14/05/2015
  3577                              <1> 	;jc	error ; 27/05/2013
  3578                              <1> 		; br  error2 / file not found
  3579                              <1>    	;pop	edx ; * ; mode ; 04/12/2021
  3580                              <1> 	;push	edx ; *
  3581                              <1> 	;;or	dx, dx
  3582                              <1> 	;or	dl, dl
  3583                              <1> 	;	; tst (sp) / is mode = 0 (2nd arg of call;
  3584                              <1> 	;	         ; / 0 means, open for read)
  3585                              <1> 	;;jz	short sysopen_0
  3586                              <1> 	;;	; beq 1f / yes, leave i-number positive
  3587                              <1> 	
  3588 00003647 8B1424              <1> 	mov	edx, [esp] ; *
  3589                              <1> 	; edx = open mode (0 or 1)
  3590                              <1> 
  3591                              <1> ;syscreat_0: ;op0: ; 27/12/2015
  3592                              <1> ;	neg	ax
  3593                              <1> ;        	; neg r1 / open for writing so make i-number negative
  3594                              <1> 
  3595                              <1> sysopen_0: ;1:
  3596 0000364A E89D200000          <1> 	call	iopen
  3597                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3598 0000364F 5A                  <1> 	pop	edx ; * ; mode ; 04/12/2021
  3599                              <1> 	;;and	dx, dx
  3600                              <1> 	;and	dl, dl
  3601                              <1>         ;	; tst (sp)+ / pop the stack and test the mode
  3602                              <1> 	;jz	short sysopen_2
  3603                              <1>         ;	; beq op1 / is open for read op1
  3604                              <1> ;sysopen_1: ;op0:
  3605                              <1> 	;neg	ax
  3606                              <1>         ;	; neg r1 
  3607                              <1> 	;	     ;/ make i-number positive if open for writing [???]
  3608                              <1> 
  3609                              <1> 	;; NOTE: iopen always make i-number positive.
  3610                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3611                              <1> sysopen_1: ; 04/12/2021
  3612                              <1> sysopen_2: ;op1:
  3613 00003650 31F6                <1>         xor     esi, esi
  3614                              <1>         	; clr r2 / clear registers
  3615 00003652 31DB                <1>         xor     ebx, ebx
  3616                              <1> 		; clr r3
  3617                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3618 00003654 389E[6E6D0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3619                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3620 0000365A 7625                <1> 	jna	short sysopen_4
  3621                              <1> 		; beq 1f / if byte in list is 0 branch
  3622 0000365C 46                  <1>         inc     esi
  3623                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3624                              <1> 	; 02/01/2022
  3625                              <1> 	;cmp	si, OPENFILES ; 04/12/2021
  3626 0000365D 6683FE0A            <1> 	cmp	si, 10
  3627                              <1> 		; cmp r2,$10. / reached end of list?
  3628 00003661 72F1                <1> 	jb	short sysopen_3
  3629                              <1> 		; blt 1b / no, go back
  3630                              <1> toomanyf:
  3631                              <1> 	; 14/05/2015
  3632 00003663 C705[D86D0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3632 0000366B 0000                <1>
  3633 0000366D E9FBFBFFFF          <1> 	jmp	error
  3634                              <1>         	; br error2 / yes, error (no files open)
  3635                              <1> fnotfound: 
  3636                              <1> 	; 14/05/2015
  3637 00003672 C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3637 0000367A 0000                <1>
  3638 0000367C E9ECFBFFFF          <1> 	jmp	error
  3639                              <1> 
  3640                              <1> sysopen_4: ; 1:
  3641 00003681 6683BB[D4690000]00  <1>         cmp     word [ebx+fsp], 0
  3642                              <1> 		; tst fsp(r3) / scan fsp entries
  3643 00003689 760D                <1>         jna     short sysopen_5
  3644                              <1> 		; beq 1f / if 0 branch
  3645                              <1> 	;; 14/05/2015 - Retro UNIX 386 v1 modification !
  3646                              <1> 	;add	bx, 10 ; fsp structure size = 10 bytes/entry
  3647                              <1> 		; add $8.,r3 / add 8 to r3 
  3648                              <1> 			; / to bump it to next entry mfsp table
  3649                              <1> 	; 01/01/2022
  3650                              <1> 	; 07/08/2020 - Retro UNIX 386 v2
  3651 0000368B 6683C310            <1> 	add	bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2
  3652                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  3653                              <1> 	;add	bx, fp.size
  3654                              <1> 
  3655                              <1> 	; 22/11/2021
  3656                              <1> 	;cmp	bx, NFILES*fp.size ; NFILES*16
  3657                              <1> 	; 02/01/2022
  3658 0000368F 6681FB2003          <1> 	cmp	bx, nfiles*16
  3659                              <1> 	; 01/01/2022
  3660                              <1> 	;cmp	bx, NFILES*16 ; NFILES*fp.size
  3661                              <1> 	;;cmp	bx, nfiles*10
  3662                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3663 00003694 72EB                <1> 	jb	short sysopen_4
  3664                              <1>        		; blt 1b / no, back
  3665                              <1> 	;jmp	error
  3666                              <1>         ;	; br error2 / yes, error
  3667                              <1> 	; 04/12/2021
  3668                              <1> 	; 07/08/2020
  3669 00003696 EBCB                <1> 	jmp	short toomanyf
  3670                              <1> 
  3671                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3672 00003698 668983[D4690000]    <1>         mov     [ebx+fsp], ax
  3673                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3674                              <1> 			; / into next available entry in fsp table,
  3675                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3676                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3677                              <1> 	;	; mov cdev,fsp+2(r3) / put # of device in next word
  3678                              <1> 
  3679                              <1> 	; 18/04/2022
  3680                              <1> 	; 04/12/2021        
  3681                              <1> 	;mov	al, [cdev]
  3682                              <1> 	;mov	ah, dl ; open mode, 0 = read, 1 = write
  3683                              <1> 	;mov	[ebx+fsp+4], ax ; device number & open mode
  3684                              <1> 
  3685                              <1> 	;xor	edi, edi
  3686                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3687                              <1> 	;	; clr fsp+4(r3)
  3688                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3689                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3690                              <1> 
  3691                              <1> 	; 04/12/2021 
  3692 0000369F 31C0                <1> 	xor	eax, eax
  3693 000036A1 8983[DC690000]      <1>   	mov	[ebx+fsp+8], eax ; offset pointer = 0
  3694                              <1> 
  3695                              <1> 	;;inc	word [ebx+fsp+6]
  3696                              <1> 	;inc	byte [ebx+fsp+6] ; open count = open count + 1	
  3697                              <1> 	; 18/04/2022
  3698                              <1> 	;mov	word [ebx+fsp+6], ax ; open count = 0 
  3699                              <1> 				     ; (sysfork increases open count)
  3700                              <1> 	; 18/04/2022		     ; reserved (mnt) flag = 0
  3701 000036A7 A0[416D0000]        <1> 	mov	al, [cdev]
  3702 000036AC 88D4                <1> 	mov	ah, dl ; open mode, 0 = read, 1 = write
  3703 000036AE 8983[D8690000]      <1> 	mov	[ebx+fsp+4], eax ; device number (al)
  3704                              <1> 				 ; & open mode (ah)
  3705                              <1> 				 ; (& open count = 0)
  3706                              <1>   	;mov	eax, ebx
  3707                              <1> 	;mov	bl, 10
  3708                              <1> 	;div	bl 
  3709                              <1> 	;	; asr r3
  3710                              <1> 	;	; asr r3 / divide by 8 
  3711                              <1> 	;	; asr r3 ; / to get number of the fsp entry-1
  3712                              <1> 	;inc	al
  3713                              <1>         ;	; inc r3 / add 1 to get fsp entry number
  3714                              <1>         ;mov	[esi+u.fp], al
  3715                              <1> 	;	; movb r3,u.fp(r2) / move entry number into 
  3716                              <1> 			; / next available slot in u.fp list
  3717                              <1> 	; 04/12/2021
  3718 000036B4 C1EB04              <1> 	shr	ebx, 4	; / 16
  3719                              <1> 	;shr	bx, 4	; bx = fsp entry number (index)	
  3720                              <1> 			; bx <= 49 for current runix 386 version
  3721 000036B7 FEC3                <1> 	inc 	bl	; bl = 1 to 50
  3722 000036B9 889E[6E6D0000]      <1> 	mov	[esi+u.fp], bl 	
  3723                              <1> 
  3724 000036BF 8935[646D0000]      <1>         mov     [u.r0], esi
  3725                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3726                              <1> 			     ; / into r0 loc on stack
  3727 000036C5 E9C3FBFFFF          <1>         jmp	sysret
  3728                              <1> 		; br sysret2
  3729                              <1> 
  3730                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3731                              <1> ;
  3732                              <1> ;         15                    7                   0
  3733                              <1> ;  1     |-------------------------------------------|
  3734                              <1> ;        |   	     i-number of open file           |
  3735                              <1> ;        |-------------------------------------------| 
  3736                              <1> ;        |        high word of 32 bit i-number       |
  3737                              <1> ;        |-------------------------------------------|
  3738                              <1> ;        | open mode & status  |   device number     |
  3739                              <1> ;        |-------------------------------------------|			
  3740                              <1> ;        |    reserved byte    |     open count      |
  3741                              <1> ;        |-------------------------------------------| 
  3742                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3743                              <1> ;        |-------------------------------------------|
  3744                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3745                              <1> ;        |-------------------------------------------|
  3746                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3747                              <1> ;        |-------------------------------------------|
  3748                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3749                              <1> ;        |-------------------------------------------|
  3750                              <1> ;  2     |                                           |
  3751                              <1> ;        |-------------------------------------------| 
  3752                              <1> ;        |                                           |
  3753                              <1> ;        |-------------------------------------------|
  3754                              <1> ;        |                                           |
  3755                              <1> ;        |-------------------------------------------|
  3756                              <1> ;        |                                           |
  3757                              <1> ;        |-------------------------------------------| 
  3758                              <1> ;        |                                           | 
  3759                              <1> 
  3760                              <1> 	;
  3761                              <1> 	; 'fsp' table (10 bytes/entry)
  3762                              <1> 	; bit 15				   bit 0
  3763                              <1> 	; ---|-------------------------------------------
  3764                              <1> 	; r/w|		i-number of open file
  3765                              <1> 	; ---|-------------------------------------------
  3766                              <1> 	;		   device number
  3767                              <1> 	; -----------------------------------------------
  3768                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3769                              <1> 	; -----------------------------------------------
  3770                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3771                              <1> 	; ----------------------|------------------------
  3772                              <1> 	;  flag that says file 	| number of processes
  3773                              <1> 	;   has been deleted	| that have file open 
  3774                              <1> 	; ----------------------|------------------------
  3775                              <1> 	;
  3776                              <1> 
  3777                              <1> 	; 12/03/2022
  3778                              <1> 	; 11/02/2022
  3779                              <1> 	; 01/01/2022
  3780                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3781                              <1> syscreat: ; < create file >
  3782                              <1> 	; 12/03/2022
  3783                              <1> 	; 11/02/2022
  3784                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3785                              <1> 	; 04/04/2021
  3786                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3787                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3788                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3789                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3790                              <1> 	;
  3791                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3792                              <1> 	; u.namep points to name of the file and mode is put
  3793                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3794                              <1> 	; If the file aready exists, it's mode and owner remain 
  3795                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3796                              <1> 	; did not exist, an i-node is created with the new mode via
  3797                              <1> 	; 'maknod' whether or not the file already existed, it is
  3798                              <1> 	; open for writing. The fsp table is then searched for a free
  3799                              <1> 	; entry. When a free entry is found, proper data is placed
  3800                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3801                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3802                              <1> 	; is put in the user's r0. 			
  3803                              <1> 	;
  3804                              <1> 	; Calling sequence:
  3805                              <1> 	;	syscreate; name; mode
  3806                              <1> 	; Arguments:
  3807                              <1> 	;	name - name of the file to be created
  3808                              <1> 	;	mode - mode of the file to be created
  3809                              <1> 	; Inputs: (arguments)
  3810                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3811                              <1> 	;		   (the file descriptor of new file)
  3812                              <1> 	; ...............................................................
  3813                              <1> 	;				
  3814                              <1> 	; Retro UNIX 8086 v1 modification: 
  3815                              <1> 	;       'syscreate' system call has two arguments; so,
  3816                              <1> 	;	* 1st argument, name is pointed to by BX register
  3817                              <1> 	;	* 2nd argument, mode is in CX register
  3818                              <1> 	;
  3819                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3820                              <1> 	;	to the user with the file descriptor/number 
  3821                              <1> 	;	(index to u.fp list).
  3822                              <1> 	;
  3823                              <1> 	;call	arg2
  3824                              <1> 	; * name - 'u.namep' points to address of file/path name
  3825                              <1> 	;          in the user's program segment ('u.segmnt')
  3826                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3827                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3828                              <1> 	;          which is on top of stack.
  3829                              <1> 	;
  3830                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3831                              <1> 			    ; / on stack
  3832 000036CA 891D[806D0000]      <1> 	mov	[u.namep], ebx ; file name address
  3833                              <1> 	;push	cx ; mode
  3834                              <1> 	; 04/12/2021
  3835 000036D0 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3836 000036D1 E8AF0A0000          <1> 	call 	namei        	
  3837                              <1> 		; jsr r0,namei / get the i-number
  3838                              <1>         ;and	ax, ax
  3839                              <1> 	;jz	short syscreat_1	       	
  3840 000036D6 7216                <1> 	jc	short syscreat_1
  3841                              <1> 		; br 2f / if file doesn't exist 2f
  3842                              <1> 	; 27/12/2015
  3843                              <1> 	;cmp	ax, 41 ; device inode ?
  3844                              <1>         ;jb	syscreat_0 ; yes
  3845                              <1> 	;
  3846                              <1> 	;neg 	ax
  3847                              <1>         ;	; neg r1 / if file already exists make i-number 
  3848                              <1> 		       ; / negative (open for writing)
  3849                              <1> 	; 11/02/2022
  3850                              <1> 	; Truncate existing file
  3851                              <1> ;syscreate_2:
  3852                              <1> 	;; 27/03/2021
  3853                              <1> 	;;xor	edx, edx ; 0
  3854                              <1> 	;;inc	dl ; DL = 1 ; create/truncate (open for write)
  3855                              <1> 	;mov	dl, 1
  3856                              <1> 	; 11/02/2022
  3857 000036D8 B202                <1> 	mov	dl, 2 ; create file (call from syscreat)
  3858 000036DA E80D200000          <1> 	call	iopen
  3859                              <1>          	; jsr r0,iopen
  3860                              <1> 	; 11/02/2022
  3861                              <1> 	; cpu will return here if inode in eax is regular file inode
  3862                              <1> 	; (if it is device or dir inode, cpu will jumpt to 'error')
  3863                              <1> 	;
  3864                              <1> 	; 12/03/2022
  3865 000036DF 50                  <1> 	push	eax ; * ; save inode number
  3866                              <1> 	; 
  3867                              <1> 	; truncate file to zero length
  3868                              <1> 	;call	itrunc
  3869                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3870                              <1> 	; 11/02/2022
  3871                              <1> 	; (iget and regular file check -in 'itrunc'- is not needed) 
  3872 000036E0 E898170000          <1> 	call	itrunc_1
  3873                              <1> 	; 12/03/2022
  3874 000036E5 58                  <1> 	pop	eax ; * ; restore inode number in eax
  3875                              <1> 	;
  3876                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3877                              <1> 	; 04/12/2021
  3878 000036E6 59                  <1> 	pop	ecx
  3879                              <1> syscreat_2:
  3880 000036E7 B201                <1> 	mov	dl, 1 ; open for writing
  3881 000036E9 E962FFFFFF          <1>         jmp     sysopen_1
  3882                              <1>         	; br op0
  3883                              <1> syscreat_1: ; 2: / file doesn't exist
  3884                              <1> 	;pop	ax
  3885                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3886                              <1> 	; 27/03/2021
  3887 000036EE 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3888                              <1> 	;xor	ah, ah	
  3889                              <1>         ;	; bic $!377,r1 / clear upper byte
  3890                              <1> 	; 27/03/2021
  3891                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3892                              <1> 	; clear bits 15,14,13,12,9 of mode (input from user)
  3893 000036EF 80E40D              <1> 	and	ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h)
  3894                              <1> 	; 11/02/2022
  3895 000036F2 80CC80              <1> 	or	ah, 80h	; IFREG (8000h) ; Regular file
  3896 000036F5 E8B40D0000          <1> 	call 	maknod
  3897                              <1>         	; jsr r0,maknod / make an i-node for this file
  3898                              <1> 	;sub	eax, eax ; 04/12/2021
  3899 000036FA 66A1[9C6D0000]      <1> 	mov	ax, [u.dirbuf]
  3900                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3901                              <1> 			        ; / for this new file in r1
  3902                              <1> 	; 04/04/2021
  3903                              <1> 	;mov	dl, 1 ; open for writing
  3904                              <1>         ;
  3905                              <1> 	;jmp	sysopen_1
  3906                              <1>         ;	; br op0 / open the file
  3907                              <1> 	; 04/04/2021
  3908 00003700 EBE5                <1> 	jmp	short syscreat_2
  3909                              <1> 
  3910                              <1> 	; 11/02/2022
  3911                              <1> 	; 04/12/2021
  3912                              <1> dir_access_err:	; 13/03/2022
  3913                              <1> ;	; 14/05/2015
  3914                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3915                              <1> ;f_create_error:
  3916                              <1> 	; 27/03/2021
  3917 00003702 C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; permission denied !	
  3917 0000370A 0000                <1>
  3918 0000370C E95CFBFFFF          <1> 	jmp	error
  3919                              <1> 
  3920                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3921                              <1> sysmkdir: ; < make directory >
  3922                              <1> 	; 13/03/2022
  3923                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3924                              <1> 	; 02/04/2021
  3925                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3926                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3927                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3928                              <1> 	;
  3929                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3930                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3931                              <1> 	; The special entries '.' and '..' are not present.
  3932                              <1> 	; Errors are indicated if the directory already exists or		
  3933                              <1> 	; user is not the super user. 
  3934                              <1> 	;
  3935                              <1> 	; Calling sequence:
  3936                              <1> 	;	sysmkdir; name; mode
  3937                              <1> 	; Arguments:
  3938                              <1> 	;	name - points to the name of the directory
  3939                              <1> 	;	mode - mode of the directory
  3940                              <1> 	; Inputs: (arguments)
  3941                              <1> 	; Outputs: -
  3942                              <1> 	;    (sets 'directory' flag to 1; 
  3943                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3944                              <1> 	; ...............................................................
  3945                              <1> 	;				
  3946                              <1> 	; Retro UNIX 8086 v1 modification: 
  3947                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3948                              <1> 	;	* 1st argument, name is pointed to by BX register
  3949                              <1> 	;	* 2nd argument, mode is in CX register
  3950                              <1> 	;
  3951                              <1> 		
  3952                              <1> ; / make a directory
  3953                              <1> 
  3954                              <1> 	;call	arg2
  3955                              <1> 	; * name - 'u.namep' points to address of file/path name
  3956                              <1> 	;          in the user's program segment ('u.segmnt')
  3957                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3958                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3959                              <1> 	;          which is on top of stack.
  3960                              <1> 
  3961                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3962                              <1> 			    ; / on stack
  3963 00003711 891D[806D0000]      <1> 	mov	[u.namep], ebx
  3964                              <1> 	;push	cx ; mode
  3965                              <1> 	; 27/03/2021
  3966 00003717 51                  <1> 	push	ecx ; cx = mode
  3967 00003718 E8680A0000          <1> 	call	namei
  3968                              <1>         	; jsr r0,namei / get the i-number
  3969                              <1>         	;     br .+4 / if file not found branch around error
  3970                              <1>         ;xor 	ax, ax
  3971                              <1> 	;jnz	error
  3972 0000371D 7334                <1> 	jnc	short dir_exists ; 14/05/2015
  3973                              <1> 	;jnc	error	
  3974                              <1> 		; br error2 / directory already exists (error)
  3975                              <1> 
  3976                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  3977                              <1>         ;	;tstb u.uid / is user the super user
  3978                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3979                              <1> 	;;jna	error
  3980                              <1>         ;	;bne error2 / no, not allowed
  3981                              <1> 	;pop	ax
  3982                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3983                              <1> 	;and	ax, 0FFCFh ; 1111111111001111b
  3984                              <1>         ;	;bic $!317,r1 / all but su and ex
  3985                              <1> 	;;or	ax, 4000h ; 1011111111111111b
  3986                              <1> 	;or	ah, 40h ; Set bit 14 to 1
  3987                              <1>         ; 	;bis $40000,r1 / directory flag
  3988                              <1> 
  3989                              <1> 	; 02/04/2021
  3990                              <1> 	;cmp	word [u.uid], 0
  3991                              <1> 	;;ja	error
  3992                              <1> 	;ja	short dir_access_err
  3993                              <1> 
  3994                              <1> 	; 13/03/2022
  3995                              <1> 	; NOTE:
  3996                              <1> 	; Unix v5-v7 kernels do not allow (ordinary) users
  3997                              <1> 	; (except root/superuser) --if [u.uid] > 0--
  3998                              <1> 	; to make a sub directory. (ref: sys2.c, 'mknod')
  3999                              <1> 	;
  4000                              <1> 	; But, Retro UNIX 386 v1.2 will allow the owner of
  4001                              <1> 	; the parent directory to make a sub directory, here.
  4002                              <1> 
  4003                              <1> 	; 13/03/2022
  4004 0000371F 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0
  4005 00003727 7618                <1> 	jna	short sysmkdir1 ; root (superuser)
  4006                              <1> 
  4007                              <1> 	; Here..
  4008                              <1> 	; (current) inode buffer contains inode structure
  4009                              <1> 	; of the parent directory (at the return of 'namei').
  4010                              <1> 
  4011 00003729 66A1[E8680000]      <1> 	mov	ax, [i.uid] ; owner ID of the parent dir
  4012 0000372F 663B05[B66D0000]    <1> 	cmp	ax, [u.uid] ; user ID of current user/process
  4013 00003736 75CA                <1> 	jne	short dir_access_err
  4014                              <1> 	; 13/03/2022
  4015                              <1> 	; additional checking (may or may not be necessary!?)
  4016 00003738 663B05[B86D0000]    <1> 	cmp	ax, [u.ruid] 
  4017                              <1> 			; real (login) user ID must be same
  4018 0000373F 75C1                <1> 	jne	short dir_access_err
  4019                              <1> 
  4020                              <1> 	; 02/04/2021
  4021                              <1> 	; ('mkdir' procedure will be called from 'maknod'
  4022                              <1> 	; and then 'mkdir' will check write access permission) 
  4023                              <1> 	; ((so, 'access_w' call is not needed here.))
  4024                              <1> 
  4025                              <1> 	;; 02/04/2021
  4026                              <1> 	;; ('make directory' user permission check)
  4027                              <1> 	;; ((current directory's write permission flags
  4028                              <1> 	;;  will be checked against user's 'uid' & gid'))
  4029                              <1> 	;mov	dx, 80h ; IWRITE
  4030                              <1> 	;call	access_w  ; (in 'access', 'u5.s')
  4031                              <1> 	;; (If cpu will return here, the user has write permission)
  4032                              <1> 
  4033                              <1> sysmkdir1:
  4034                              <1> 	; 27/03/2021
  4035 00003741 58                  <1> 	pop	eax  ; ax = mode
  4036                              <1> 	; [ii] = current directory's inode number
  4037                              <1> 
  4038                              <1> 	; 27/03/2021
  4039                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  4040                              <1> 	; clear bits 13,12,11,10,9,6,3,0 of mode (input from user)
  4041                              <1> 	;and	ax, 0C1B6h ; bits 15,14,8,7,5,4,2,1
  4042 00003742 6625B601            <1> 	and	ax, 01B6h
  4043 00003746 80CCC0              <1> 	or	ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 
  4044                              <1> 			 ; Directory
  4045 00003749 E8600D0000          <1> 	call	maknod
  4046                              <1>         	;jsr r0,maknod / make the i-node for the directory
  4047 0000374E E93AFBFFFF          <1> 	jmp	sysret
  4048                              <1>         	;br sysret2 /
  4049                              <1> dir_exists:
  4050                              <1> 	; 27/03/2021
  4051                              <1> 	; (same error number for files and directories)
  4052                              <1> 	; Error Number: 14 (ERR_DIR_EXISTS)
  4053 00003753 C705[D86D0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS
  4053 0000375B 0000                <1>
  4054                              <1> 				; 'file already exists !' error
  4055                              <1> 	; 04/12/2021
  4056 0000375D E90BFBFFFF          <1> 	jmp	error
  4057                              <1> ;dir_access_err:
  4058                              <1> ;	; 14/05/2015
  4059                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  4060                              <1> ;	jmp	error
  4061                              <1> 
  4062                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4063                              <1> sysclose: ;<close file>
  4064                              <1> 	; 02/03/2022
  4065                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4066                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4067                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  4068                              <1> 	;
  4069                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  4070                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  4071                              <1> 	; is put in r1 and 'fclose' is called.
  4072                              <1> 	;
  4073                              <1> 	; Calling sequence:
  4074                              <1> 	;	sysclose
  4075                              <1> 	; Arguments:
  4076                              <1> 	;	-  
  4077                              <1> 	; Inputs: *u.r0 - file descriptor
  4078                              <1> 	; Outputs: -
  4079                              <1> 	; ...............................................................
  4080                              <1> 	;				
  4081                              <1> 	; Retro UNIX 8086 v1 modification:
  4082                              <1> 	;	 The user/application program puts file descriptor
  4083                              <1> 	;        in BX register as 'sysclose' system call argument.
  4084                              <1> 	; 	 (argument transfer method 1)
  4085                              <1> 
  4086                              <1> 	; / close the file
  4087                              <1> 	
  4088                              <1> 	;mov 	eax, ebx
  4089                              <1> 	; 04/12/2021
  4090                              <1> 	; ebx = file descriptor/number
  4091                              <1> 	;call 	fclose
  4092                              <1> 	; 02/03/2022
  4093 00003762 E8A2090000          <1> 	call	_fclose
  4094                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  4095                              <1> 		; jsr r0,fclose / close the file
  4096                              <1>                	; br error2 / unknown file descriptor
  4097                              <1> 		; br sysret2
  4098                              <1> 	;; 14/05/2015
  4099                              <1> 	;jnc	sysret
  4100                              <1> 	; 04/12/2021
  4101 00003767 7205                <1> 	jc	short sysclose_err
  4102 00003769 E91FFBFFFF          <1> 	jmp	sysret
  4103                              <1> sysclose_err:
  4104 0000376E C705[D86D0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  4104 00003776 0000                <1>
  4105 00003778 E9F0FAFFFF          <1> 	jmp	error
  4106                              <1> 
  4107                              <1> 	; 23/02/2022
  4108                              <1> 	; 19/12/2021
  4109                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4110                              <1> sysemt:
  4111                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4112                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4113                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  4114                              <1> 	;
  4115                              <1> 	; Retro UNIX 8086 v1 modification: 
  4116                              <1> 	;	'Enable Multi Tasking' system call instead 
  4117                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  4118                              <1> 	;
  4119                              <1> 	; Retro UNIX 8086 v1 feature only!
  4120                              <1> 	;	Using purpose: Kernel will start without time-out
  4121                              <1> 	;	(internal clock/timer) functionality.
  4122                              <1> 	;	Then etc/init will enable clock/timer for
  4123                              <1> 	;	multi tasking. (Then it will not be disabled again
  4124                              <1> 	;	except hardware reset/restart.)
  4125                              <1> 	;
  4126                              <1> 	
  4127                              <1> 	;cmp	byte [u.uid], 0 ; root ?
  4128                              <1> 	;;ja	error
  4129                              <1> 	;ja	badsys ; 14/05/2015
  4130                              <1> 	; 04/12/2021
  4131 0000377D 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0 ; root ?
  4132 00003785 7605                <1> 	jna	short emt_0 
  4133 00003787 E993FBFFFF          <1> 	jmp	badsys
  4134                              <1> emt_0:
  4135 0000378C FA                  <1> 	cli	; 23/02/2022
  4136 0000378D 21DB                <1> 	and	ebx, ebx
  4137 0000378F 7429                <1> 	jz	short emt_2
  4138                              <1> 	; Enable multi tasking -time sharing-
  4139 00003791 B8[23480000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  4140                              <1> 	; 23/02/2022
  4141 00003796 BA[2B0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  4142                              <1> emt_1:
  4143 0000379B A3[F0060000]        <1> 	mov	[x_timer], eax
  4144                              <1> 	; 23/02/2022 (Temporary)
  4145 000037A0 8915[F4060000]      <1> 	mov	[x_rtci], edx
  4146 000037A6 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  4147 000037A8 E855020000          <1> 	call	wttyc  ; clear video page
  4148 000037AD B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  4149 000037AF E84E020000          <1> 	call	wttyc  ; clear video page
  4150                              <1> 	;
  4151 000037B4 FB                  <1> 	sti	; 23/02/2022
  4152 000037B5 E9D3FAFFFF          <1> 	jmp	sysret
  4153                              <1> emt_2:
  4154                              <1> 	; Disable multi tasking -time sharing-
  4155 000037BA B8[FC060000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  4156                              <1> 	; 23/02/2022
  4157 000037BF BA[320A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  4158                              <1> 	;
  4159 000037C4 EBD5                <1> 	jmp	short emt_1
  4160                              <1> 
  4161                              <1> 	; Original UNIX v1 'sysemt' routine
  4162                              <1> ;sysemt:
  4163                              <1>         ;
  4164                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  4165                              <1> 			 ; / in loc 30
  4166                              <1>         ;cmp    30,$core / was the argument a lower address 
  4167                              <1> 			; / than core
  4168                              <1>         ;blo    1f / yes, rtssym
  4169                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  4170                              <1> 			; / and less than "ecore"
  4171                              <1>         ;blo    2f / yes, sysret2
  4172                              <1> ;1:
  4173                              <1>         ;mov    $rtssym,30
  4174                              <1> ;2:
  4175                              <1>         ;br     sysret2
  4176                              <1> 
  4177                              <1> sysilgins:
  4178                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4179                              <1> 	; 03/06/2013
  4180                              <1> 	; Retro UNIX 8086 v1 modification: 
  4181                              <1> 	;	not a valid system call ! (not in use)
  4182                              <1> 	;
  4183 000037C6 E954FBFFFF          <1> 	jmp	badsys
  4184                              <1> 	;jmp	error
  4185                              <1> 	;;jmp 	sysret
  4186                              <1> 
  4187                              <1> 	; Original UNIX v1 'sysemt' routine
  4188                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  4189                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  4190                              <1> 			  ;/ put it in loc 8.,
  4191                              <1>         ;cmp    10,$core / making it the illegal instruction 
  4192                              <1> 		       ; / trap address
  4193                              <1>         ;blo    1f / is the address a user core address?  
  4194                              <1> 		; / yes, go to 2f
  4195                              <1>         ;cmp    10,$ecore
  4196                              <1>         ;blo    2f
  4197                              <1> ;1:
  4198                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  4199                              <1> 		    ; / instruction trap address for the system
  4200                              <1> ;2:
  4201                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  4202                              <1> 
  4203                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4204                              <1> sysmdate: ; < change the modification time of a file >
  4205                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  4206                              <1> 	;	(ECX input)
  4207                              <1> 	; 24/12/2021
  4208                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4209                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  4210                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4211                              <1> 	;
  4212                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  4213                              <1> 	; file into core. The user is checked if he is the owner 
  4214                              <1> 	; or super user. If he is neither an error occurs.
  4215                              <1> 	; 'setimod' is then called to set the i-node modification
  4216                              <1> 	; byte and the modification time, but the modification time
  4217                              <1> 	; is overwritten by whatever get put on the stack during
  4218                              <1> 	; a 'systime' system call. This calls are restricted to
  4219                              <1> 	; the super user.		
  4220                              <1> 	;
  4221                              <1> 	; Calling sequence:
  4222                              <1> 	;	sysmdate; name
  4223                              <1> 	; Arguments:
  4224                              <1> 	;	name - points to the name of file
  4225                              <1> 	; Inputs: (arguments)
  4226                              <1> 	; Outputs: -
  4227                              <1> 	; ...............................................................
  4228                              <1> 	;				
  4229                              <1> 	; Retro UNIX 8086 v1 modification: 
  4230                              <1> 	;	 The user/application program puts address 
  4231                              <1> 	;	 of the file name in BX register 
  4232                              <1> 	;	 as 'sysmdate' system call argument.
  4233                              <1> 	;
  4234                              <1> ; / change the modification time of a file
  4235                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4236 000037CB 891D[806D0000]      <1>         mov	[u.namep], ebx
  4237                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  4238 000037D1 890D[70680000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  4239 000037D7 E8A9090000          <1> 	call	namei
  4240                              <1> 		; jsr r0,namei / get its i-number
  4241                              <1> 	;;jc	error       
  4242                              <1> 	;	; br error2 / no, such file
  4243                              <1> 	;jc	fnotfound ; file not found !
  4244                              <1> 	; 24/12/2021
  4245 000037DC 7305                <1> 	jnc	short mdate_0
  4246 000037DE E98FFEFFFF          <1> 	jmp	fnotfound
  4247                              <1> mdate_0: 
  4248 000037E3 E89D140000          <1> 	call	iget
  4249                              <1> 		; jsr r0,iget / get i-node into core
  4250                              <1> 	;mov	al, [u.uid]
  4251                              <1> 	;cmp	al, [i.uid]
  4252                              <1>         ;	; cmpb u.uid,i.uid / is user same as owner
  4253                              <1> 	;je	short mdate_1
  4254                              <1>         ;	; beq 1f / yes
  4255                              <1> 	;and	al, al
  4256                              <1> 	;	; tstb u.uid / no, is user the super user
  4257                              <1> 	;;jnz	error
  4258                              <1> 	;	; bne error2 / no, error
  4259                              <1> 	;jz	short mdate_1
  4260                              <1> 	; 04/12/2021
  4261 000037E8 66A1[B66D0000]      <1> 	mov	ax, [u.uid]
  4262 000037EE 663B05[E8680000]    <1> 	cmp	ax, [i.uid]
  4263 000037F5 7414                <1> 	je	short mdate_1	
  4264 000037F7 6621C0              <1> 	and	ax, ax
  4265 000037FA 740F                <1> 	jz	short mdate_1
  4266                              <1> 
  4267 000037FC C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4267 00003804 0000                <1>
  4268                              <1> sysstty_err:	; 06/02/2022
  4269 00003806 E962FAFFFF          <1> 	jmp	error
  4270                              <1> mdate_1: ;1:
  4271 0000380B E806160000          <1> 	call	setimod
  4272                              <1>         	; jsr r0,setimod / fill in modification data,
  4273                              <1> 		               ; / time etc.
  4274 00003810 BE[70680000]        <1> 	mov	esi, p_time
  4275 00003815 BF[1C690000]        <1> 	mov	edi, i.mtim
  4276 0000381A A5                  <1> 	movsd
  4277                              <1> 		; mov 4(sp),i.mtim / move present time to
  4278                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4279 0000381B E96DFAFFFF          <1>         jmp	sysret
  4280                              <1> 		; br sysret2
  4281                              <1> 
  4282                              <1> 	; 06/02/2022
  4283                              <1> sysstty_err_s:
  4284 00003820 880D[646D0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4285 00003826 EBDE                <1> 	jmp	short sysstty_err
  4286                              <1> 
  4287                              <1> sysstty: ; < set tty status and mode >
  4288                              <1> 	; 22/02/2022
  4289                              <1> 	; 21/02/2022
  4290                              <1> 	; 06/02/2022 (Retro UNIX 286 v1.2)
  4291                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4292                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4293                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4294                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4295                              <1> 	;	    ((32 bit reg push/pop))
  4296                              <1> 	; 17/11/2015
  4297                              <1> 	; 12/11/2015
  4298                              <1> 	; 29/10/2015
  4299                              <1> 	; 17/10/2015
  4300                              <1> 	; 13/10/2015
  4301                              <1> 	; 29/06/2015
  4302                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4303                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4304                              <1> 	;
  4305                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4306                              <1> 	; whose file descriptor is in (u.r0).
  4307                              <1> 	;
  4308                              <1> 	; Calling sequence:
  4309                              <1> 	;	sysstty; arg
  4310                              <1> 	; Arguments:
  4311                              <1> 	;	arg - address of 3 consequitive words that contain
  4312                              <1> 	;	      the source of status data	
  4313                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4314                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4315                              <1> 	; ...............................................................
  4316                              <1> 	;	
  4317                              <1> 	; Retro UNIX 8086 v1 modification: 
  4318                              <1> 	;	'sysstty' system call will set the tty
  4319                              <1> 	;	(clear keyboard buffer and set cursor position)
  4320                              <1> 	;	 in following manner:
  4321                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4322                              <1> 	;
  4323                              <1> 	; Inputs:
  4324                              <1> 	;	BX = 0 --> means
  4325                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4326                              <1> 	;	      set cursor position for console tty, only 
  4327                              <1> 	;	      CH will be ignored (char. will not be written)
  4328                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4329                              <1> 	;	      set console tty for (current) process
  4330                              <1> 	;	      CL = tty number (0 to 9)
  4331                              <1> 	;	      (If CH = 0, character will not be written)
  4332                              <1> 	;          If CH > 0 (CL < FFh)	
  4333                              <1> 	;             CL = tty number (0 to 9)
  4334                              <1> 	;	      CH = character will be written
  4335                              <1> 	;	        at requested cursor position (in DX)
  4336                              <1> 	;	   DX = cursor position for tty number 0 to 7.
  4337                              <1>   	;		(only tty number 0 to 7) 
  4338                              <1> 	;          DL = communication parameters (for serial ports)
  4339                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4340                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4341                              <1> 	;			or set cursor position	
  4342                              <1> 	;	   DH = 0FFh -> DL is not valid
  4343                              <1> 	;		do not set serial port parameters 
  4344                              <1> 	;		or do not set cursor position
  4345                              <1> 	;
  4346                              <1> 	;	BX > 0 --> points to name of tty
  4347                              <1> 	;    	   CH > 0 -->
  4348                              <1> 	;		CH = character will be written in current 
  4349                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4350                              <1> 	;	     	or character will be sent to serial port
  4351                              <1> 	;	     	(for tty number 8 or 9)
  4352                              <1> 	;		CL = color of the character if tty number < 8.
  4353                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4354                              <1> 	;		set mode (tty 8 to 9) or 
  4355                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4356                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4357                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4358                              <1> 	;		(DL is not valid)
  4359                              <1> 	;	   DL = communication parameters 
  4360                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4361                              <1> 	;
  4362                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4363                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4364                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4365                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4366                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4367                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4368                              <1> 	;
  4369                              <1> 	; Outputs:
  4370                              <1> 	;	cf = 0 -> OK
  4371                              <1> 	;	     AL = tty number (0 to 9)
  4372                              <1> 	;	     AH = line status if tty number is 8 or 9
  4373                              <1> 	;	     AH = process number (of the caller)
  4374                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4375                              <1> 	;	     AH = FFh if the tty is locked 
  4376                              <1> 	;		  (owned by another process)
  4377                              <1> 	;	        = process number (of the caller) 
  4378                              <1> 	;		  (if < FFh and tty number < 8)
  4379                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4380                              <1> 	;	     AH = line status if tty number is 8 or 9
  4381                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4382                              <1> 	;	
  4383                              <1> 
  4384                              <1> 	; 27/06/2015 (32 bit modifications)
  4385                              <1> 	; 14/01/2014
  4386 00003828 31C0                <1> 	xor 	eax, eax
  4387 0000382A 6648                <1> 	dec	ax ; 17/10/2015
  4388 0000382C A3[646D0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4389                              <1> 	;;;
  4390                              <1> 	; 01/02/2022
  4391 00003831 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4392 00003833 39C2                <1> 	cmp	edx, eax
  4393                              <1> 	;cmp	dx, ax ; 0FFFFh
  4394 00003835 7521                <1> 	jne	short sysstty_18
  4395                              <1> 	; clear video page
  4396                              <1> 	; (CH must be 0)
  4397 00003837 08ED                <1> 	or	ch, ch
  4398 00003839 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4399 0000383B 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4400 0000383E 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4401 00003840 20C9                <1> 	and	cl, cl
  4402 00003842 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4403 00003844 0FB635[B56D0000]    <1> 	movzx	esi, byte [u.uno]
  4404 0000384B 8A8E[63690000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4405 00003851 80F907              <1> 	cmp	cl, 7
  4406 00003854 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4407                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4408 00003856 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4409                              <1> sysstty_18:
  4410 00003858 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4411                              <1> 	; cl = video page (tty) number
  4412                              <1> 	;;;
  4413 0000385A 21DB                <1> 	and	ebx, ebx
  4414                              <1> 	;jnz	sysstty_6
  4415                              <1> 	; 01/02/2022
  4416 0000385C 7405                <1> 	jz	short sysstty_19
  4417 0000385E E9C2000000          <1> 	jmp	sysstty_6
  4418                              <1> sysstty_19:
  4419                              <1> 	; set console tty
  4420                              <1> 	; 29/10/2015
  4421                              <1> 	; 17/01/2014 
  4422 00003863 80F909              <1> 	cmp	cl, 9
  4423 00003866 7613                <1> 	jna	short sysstty_0
  4424                              <1> 	; 17/11/2015
  4425 00003868 80F9FF              <1> 	cmp	cl, 0FFh
  4426 0000386B 7202                <1> 	jb	short sysstty_13
  4427 0000386D 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4428                              <1> sysstty_13:
  4429 0000386F 8A1D[B56D0000]      <1> 	mov	bl, [u.uno] ; process number
  4430 00003875 8A8B[63690000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4431                              <1> sysstty_0:
  4432                              <1> 	; 29/06/2015
  4433 0000387B 52                  <1> 	push	edx ; 24/12/2021
  4434 0000387C 51                  <1> 	push	ecx
  4435 0000387D 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4436 0000387F 88C8                <1> 	mov	al, cl
  4437 00003881 A2[646D0000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4438 00003886 E82E1F0000          <1> 	call	ottyp
  4439 0000388B 59                  <1> 	pop	ecx
  4440 0000388C 5A                  <1> 	pop	edx
  4441                              <1> 	;
  4442 0000388D 7220                <1> 	jc	short sysstty_pd_err
  4443                              <1> 	;
  4444                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4445                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4446                              <1> 	;
  4447 0000388F 80F908              <1> 	cmp	cl, 8
  4448 00003892 720C                <1> 	jb	short sysstty_2
  4449                              <1> 	;
  4450 00003894 80FEFF              <1> 	cmp	dh, 0FFh
  4451 00003897 7407                <1> 	je	short sysstty_2
  4452                              <1> 
  4453                              <1> ; 01/02/2022
  4454                              <1> ;	; 29/10/2015
  4455                              <1> ;	mov	ah, dl ; communication parameters
  4456                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4457                              <1> ;		;			 THRE int + RDA int 
  4458                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4459                              <1> ;		;			 THRE int + RDA int 
  4460                              <1> ;	sub	al, al ; 0
  4461                              <1> ;	; 12/07/2014
  4462                              <1> ;	cmp	cl, 9
  4463                              <1> ;	jb	short sysstty_1
  4464                              <1> ;	inc	al
  4465                              <1> ;sysstty_1:
  4466                              <1> ;	; 01/02/2022
  4467                              <1> ;	push	ecx
  4468                              <1> ;	; 29/06/2015	
  4469                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4470                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4471                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4472                              <1> ;	; 01/02/2022
  4473                              <1> ;	pop	ecx	
  4474                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4475                              <1> 
  4476                              <1> 	; 01/02/2022
  4477 00003899 E831010000          <1> 	call	sysstty_scp
  4478 0000389E 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4479                              <1> 
  4480                              <1> sysstty_2:
  4481                              <1> 	; 17/01/2014
  4482 000038A0 20ED                <1> 	and	ch, ch 	; set cursor position 
  4483                              <1> 			; or comm. parameters ONLY
  4484 000038A2 7527                <1> 	jnz	short sysstty_3
  4485                              <1> 	; 01/02/2022
  4486 000038A4 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4487 000038A8 7214                <1> 	jb	short sysstty_20
  4488                              <1> 	; clear screen (video page)
  4489 000038AA E93C010000          <1> 	jmp	sysstty_14
  4490                              <1> 
  4491                              <1> sysstty_pd_err: ; 29/06/2015
  4492                              <1> 	; 'permission denied !' error
  4493 000038AF C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4493 000038B7 0000                <1>
  4494 000038B9 E9AFF9FFFF          <1> 	jmp	error
  4495                              <1> 
  4496                              <1> sysstty_20:
  4497 000038BE 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4498 000038C5 888B[63690000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4499                              <1> sysstty_3:
  4500                              <1> 	; 16/01/2014
  4501 000038CB 88E8                <1> 	mov	al, ch ; character  ; 0 to FFh
  4502                              <1> 	; 17/11/2015
  4503 000038CD B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4504 000038CF 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4505                              <1>         ;jna	sysstty_9
  4506                              <1> 	; 24/12/2021
  4507 000038D1 7705                <1> 	ja	short sysstty_12
  4508 000038D3 E9C6000000          <1> 	jmp	sysstty_9
  4509                              <1> 
  4510                              <1> sysstty_12:
  4511                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4512                              <1> 	; (Set specified serial port as console tty port)
  4513                              <1> 	; CH = character to be written
  4514                              <1> 	; 15/04/2014
  4515                              <1> 	; CH = 0 --> initialization only
  4516                              <1> 	; AL = character
  4517                              <1> 	; 26/06/2014
  4518 000038D8 880D[996D0000]      <1> 	mov	[u.ttyn], cl
  4519                              <1> 	; 12/07/2014
  4520 000038DE 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4521                              <1> 	; 02/02/2022
  4522 000038E0 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4523 000038E2 740B                <1> 	jz	short sysstty_4 ; al = ch = 0
  4524 000038E4 FEC8                <1> 	dec	al  ; 1 -> 0	
  4525                              <1> 	;and	al, al
  4526 000038E6 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4527                              <1>  	; 04/07/2014
  4528 000038E8 E8F7230000          <1> 	call 	sndc
  4529                              <1> 	; 12/07/2014
  4530 000038ED EB0C                <1> 	jmp	short sysstty_5
  4531                              <1> 
  4532                              <1> sysstty_4:
  4533                              <1> 	; 12/07/2014
  4534                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4535 000038EF 88E0                <1> 	mov	al, ah ; 29/06/2015
  4536 000038F1 2C08                <1> 	sub	al, 8
  4537                              <1> 	; 27/06/2015
  4538 000038F3 E8B0F3FFFF          <1> 	call	sp_status ; get serial port status
  4539                              <1> 	; AL = Line status, AH = Modem status
  4540                              <1> 	; 12/11/2015
  4541 000038F8 3C80                <1> 	cmp	al, 80h
  4542 000038FA F5                  <1> 	cmc
  4543                              <1> sysstty_5:
  4544 000038FB 66A3[656D0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4545                              <1> 		; EAX bits 16-23 = modem status	
  4546 00003901 9C                  <1> 	pushf
  4547 00003902 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4548 00003904 A0[996D0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4549 00003909 E8DE1F0000          <1> 	call	cttyp
  4550 0000390E 9D                  <1> 	popf
  4551                              <1> 	;jnc	sysret ; time out error 
  4552                              <1> 	; 01/02/2022
  4553 0000390F 7205                <1> 	jc	short sysstty_tmout_err
  4554 00003911 E977F9FFFF          <1> 	jmp	sysret
  4555                              <1> 
  4556                              <1> 	; time out error 
  4557                              <1> sysstty_tmout_err:
  4558 00003916 C705[D86D0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4558 0000391E 0000                <1>
  4559 00003920 E948F9FFFF          <1> 	jmp	error
  4560                              <1> 
  4561                              <1> sysstty_6:
  4562 00003925 52                  <1> 	push	edx ; 24/12/2021
  4563 00003926 51                  <1> 	push	ecx
  4564 00003927 891D[806D0000]      <1> 	mov	[u.namep], ebx
  4565 0000392D E853080000          <1> 	call	namei
  4566 00003932 59                  <1> 	pop	ecx
  4567 00003933 5A                  <1> 	pop	edx
  4568 00003934 7259                <1> 	jc	short sysstty_inv_dn
  4569                              <1> 	;
  4570                              <1> 	; 21/02/2022
  4571                              <1> 	;cmp	ax, 19  ; inode number of /dev/COM2
  4572                              <1> 	;ja	short sysstty_inv_dn ; 27/06/2015
  4573                              <1> 	;;
  4574                              <1> 	;cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4575                              <1> 	;	       ; /dev/COM1, /dev/COM2
  4576                              <1> 	;jb	short sysstty_7
  4577                              <1> 	;sub	al, 10
  4578                              <1> 	;jmp	short sysstty_8
  4579                              <1> 	;
  4580                              <1> 	; 21/02/2022
  4581                              <1> 	; (Retro UNIX 386 v2 file system inode numbers)
  4582 00003936 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  4583 00003939 7754                <1> 	ja	short sysstty_inv_dn
  4584                              <1> 	;cmp	al, 8	; /dev/tty inode number is 8
  4585                              <1> 	;jb	short sysstty_inv_dn
  4586 0000393B 2C08                <1> 	sub	al, 8
  4587 0000393D 7250                <1> 	jb	short sysstty_inv_dn
  4588 0000393F 7408                <1> 	jz	short sysstty_7 ; /dev/tty inode number is 8
  4589                              <1> 	; convert inode number to tty number (tty0 to tty9)
  4590 00003941 2C09                <1> 	sub	al, 9
  4591 00003943 724A                <1> 	jb	short sysstty_inv_dn
  4592                              <1> 	; al = 0 to 9
  4593 00003945 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4594 00003947 EB0D                <1> 	jmp	short sysstty_8 
  4595                              <1> sysstty_7:
  4596                              <1> 	; 21/02/2022
  4597                              <1> 	;cmp	al, 1 ; /dev/tty
  4598                              <1> 	;jne	short sysstty_inv_dn ; 27/06/2015
  4599 00003949 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4600 00003950 8A83[63690000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4601                              <1> sysstty_8:
  4602                              <1> 	; 22/02/2022
  4603                              <1> 	; (ebx < 256)	
  4604 00003956 A2[646D0000]        <1> 	mov	[u.r0], al
  4605 0000395B 52                  <1> 	push	edx ; 24/12/2021
  4606 0000395C 50                  <1> 	push	eax
  4607 0000395D 51                  <1> 	push	ecx	
  4608 0000395E E8561E0000          <1> 	call	ottyp
  4609 00003963 59                  <1> 	pop	ecx
  4610 00003964 58                  <1> 	pop	eax
  4611 00003965 5A                  <1> 	pop	edx
  4612                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4613                              <1> 	; 06/02/2022
  4614 00003966 7305                <1> 	jnc	short sysstty_21
  4615                              <1> 	; 'permission denied !'
  4616 00003968 E942FFFFFF          <1> 	jmp	sysstty_pd_err
  4617                              <1> sysstty_21:
  4618                              <1> 	; 29/10/2015
  4619 0000396D 86E9                <1> 	xchg 	ch, cl
  4620                              <1> 		; cl = character, ch = color code
  4621 0000396F 86C1                <1> 	xchg	al, cl
  4622                              <1> 		; al = character, cl = tty number
  4623 00003971 80F907              <1> 	cmp	cl, 7
  4624                              <1> 	;ja	sysstty_12
  4625                              <1> 	; 06/02/2022
  4626 00003974 7628                <1> 	jna	short sysstty_16
  4627                              <1> ;;
  4628 00003976 80FEFF              <1> 	cmp	dh, 0FFh
  4629 00003979 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4630                              <1> 
  4631                              <1> ; 01/02/2022
  4632                              <1> ;	; 29/10/2015
  4633                              <1> ;	mov	ah, dl ; communication parameters
  4634                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4635                              <1> ;		;			 THRE int + RDA int 
  4636                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4637                              <1> ;		;			 THRE int + RDA int 
  4638                              <1> ;	sub	al, al ; 0
  4639                              <1> ;	; 12/07/2014
  4640                              <1> ;	cmp	cl, 9
  4641                              <1> ;	jb	short sysstty_1
  4642                              <1> ;	inc	al
  4643                              <1> ;sysstty_1:
  4644                              <1> ;	; 01/02/2022
  4645                              <1> ;	push	ecx
  4646                              <1> ;	; 29/06/2015	
  4647                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4648                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4649                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4650                              <1> ;	; 01/02/2022
  4651                              <1> ;	pop	ecx	
  4652                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4653                              <1> 
  4654                              <1> 	; 02/02/2022
  4655 0000397B 88C5                <1> 	mov	ch, al ; save char
  4656                              <1> 	; 01/02/2022
  4657 0000397D E84D000000          <1> 	call	sysstty_scp
  4658 00003982 7292                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4659                              <1> 	; 02/02/2022
  4660 00003984 88E8                <1> 	mov	al, ch ; restore char
  4661                              <1> sysstty_22:
  4662                              <1> 	; 01/02/2022
  4663 00003986 08ED                <1> 	or	ch, ch
  4664 00003988 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4665                              <1> 	; send char to (serial port) terminal
  4666                              <1> 	; al = character
  4667                              <1> 	; cl = tty number (8 or 9)
  4668 0000398A E949FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4669                              <1> 
  4670                              <1> sysstty_inv_dn: 
  4671                              <1> 	; 27/06/2015
  4672                              <1> 	; Invalid device name (not a tty) ! error
  4673                              <1> 	; (Device is not a tty or device name not found)
  4674 0000398F C705[D86D0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4674 00003997 0000                <1>
  4675 00003999 E9CFF8FFFF          <1> 	jmp	error
  4676                              <1> 
  4677                              <1> sysstty_16:
  4678                              <1> 	; 22/02/2022
  4679                              <1> 	; 16/01/2014
  4680                              <1> 	;xor	bh, bh
  4681                              <1> sysstty_9: 	; tty 0 to tty 7
  4682                              <1> 	; al = character
  4683                              <1> 	; ch = color/attribute ; 01/02/2022
  4684                              <1> 	;
  4685                              <1>  	; 22/02/2022 (BugFix)
  4686                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4687 0000399E 29DB                <1> 	sub	ebx, ebx ; *
  4688 000039A0 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4689                              <1> 	;
  4690 000039A2 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4691 000039A5 7409                <1> 	je	short sysstty_10
  4692                              <1> 	; 24/12/2021
  4693 000039A7 51                  <1> 	push	ecx
  4694 000039A8 50                  <1> 	push	eax
  4695                              <1> 	; 22/02/2022	
  4696                              <1> 	;;movzx	ebx, cl ; *
  4697                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4698 000039A9 E8FDDAFFFF          <1> 	call	set_cpos
  4699 000039AE 58                  <1> 	pop	eax
  4700 000039AF 59                  <1> 	pop	ecx
  4701                              <1> sysstty_10: 
  4702                              <1> 	; 22/02/2022
  4703                              <1> 	; bl = video page (tty) number 
  4704                              <1> 	;
  4705                              <1> 	; 29/10/2015
  4706 000039B0 08C0                <1> 	or	al, al ; character
  4707 000039B2 740D                <1> 	jz      short sysstty_11 ; al = 0
  4708                              <1> 	; 17/11/2015
  4709 000039B4 3CFF                <1> 	cmp	al, 0FFh
  4710 000039B6 7309                <1> 	jnb	short sysstty_11
  4711                              <1> 		; ch > 0 and ch < FFh
  4712                              <1> 	; write a character at current cursor position
  4713 000039B8 88EC                <1> 	mov	ah, ch ; color/attribute
  4714                              <1> 	; 12/07/2014
  4715 000039BA 51                  <1> 	push	ecx ; 24/12/2021
  4716 000039BB E8D3DBFFFF          <1> 	call	write_c_current
  4717 000039C0 59                  <1> 	pop	ecx
  4718                              <1> sysstty_11:
  4719                              <1> 	; 14/01/2014
  4720 000039C1 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4721                              <1> 	; 18/01/2014
  4722                              <1> 	;movzx	eax, cl ; 27/06/2015
  4723 000039C3 88C8                <1> 	mov	al, cl
  4724 000039C5 E8221F0000          <1> 	call	cttyp
  4725 000039CA E9BEF8FFFF          <1> 	jmp	sysret
  4726                              <1> 
  4727                              <1> 	; 06/02/2022 (Retro UNIX 386 v1.2)
  4728                              <1> sysstty_scp:
  4729                              <1> 	; 02/02/2022
  4730                              <1> 	; set communication parameters (for COM1 or COM2)
  4731                              <1> 	; 01/02/2022
  4732                              <1> 	;
  4733                              <1> 	; 29/10/2015
  4734 000039CF 88D4                <1> 	mov	ah, dl ; communication parameters
  4735                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4736                              <1> 		;			 THRE int + RDA int 
  4737                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4738                              <1> 		;			 THRE int + RDA int 
  4739 000039D1 28C0                <1> 	sub	al, al ; 0
  4740                              <1> 	; 12/07/2014
  4741 000039D3 80F909              <1> 	cmp	cl, 9
  4742 000039D6 7202                <1> 	jb	short sysstty_1
  4743 000039D8 FEC0                <1> 	inc	al
  4744                              <1> sysstty_1:
  4745                              <1> 	; 02/02/2022
  4746 000039DA 52                  <1> 	push	edx
  4747                              <1> 	; 01/02/2022
  4748 000039DB 51                  <1> 	push	ecx
  4749                              <1> 	; 29/06/2015	
  4750 000039DC E8CFF2FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4751 000039E1 66890D[656D0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4752                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4753                              <1> 	; 01/02/2022
  4754 000039E8 59                  <1> 	pop	ecx	
  4755 000039E9 5A                  <1> 	pop	edx ; 02/02/2022
  4756                              <1> 	; 01/02/2022
  4757                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4758 000039EA C3                  <1> 	retn
  4759                              <1> 
  4760                              <1> 	; 06/02/2022 (Retro UNIX 386 v1.2)
  4761                              <1> sysstty_14:
  4762                              <1> 	; 23/02/2022
  4763                              <1> 	; 02/02/2022
  4764                              <1> 	; ch = 0
  4765                              <1> 	; cl = video page
  4766                              <1> 	;
  4767                              <1> 	; dx = 0FFFFh
  4768                              <1> 	; clear screen (video page)
  4769                              <1> 	;
  4770                              <1> 
  4771                              <1> 	; 02/02/2022
  4772                              <1> 	; clear screen
  4773                              <1> 	;
  4774                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4775                              <1> 
  4776                              <1> 	; 23/02/2022
  4777 000039EB 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4778                              <1> 
  4779                              <1> 	; clear video page
  4780 000039ED E810000000          <1> 	call	wttyc ; 23/02/2022
  4781                              <1> 
  4782                              <1> 	; 23/02/2022
  4783 000039F2 88D8                <1> 	mov	al, bl
  4784 000039F4 8A25[B56D0000]      <1> 	mov	ah, [u.uno]
  4785 000039FA 66A3[646D0000]      <1> 	mov	[u.r0], ax
  4786 00003A00 EBBF                <1> 	jmp	short sysstty_11
  4787                              <1> 
  4788                              <1> wttyc:
  4789                              <1> 	; 23/02/2022
  4790                              <1> 	; (clear video page)
  4791                              <1> 	; INPUT:
  4792                              <1> 	;  bl = video page (0 to 7)
  4793                              <1> 	;
  4794                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4795                              <1> 
  4796                              <1> 	;xor	dx, dx ; column 0, row 0
  4797                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4798                              <1> 	;
  4799                              <1> ;	movzx	ebx, cl
  4800                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4801                              <1> 
  4802                              <1> ;	shl 	bl, 1 
  4803                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4804                              <1> ;		; AL = lock value (0 or process number)
  4805                              <1> ;	or	al, al
  4806                              <1> ;	jz	short @f
  4807                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4808                              <1> ;	jne	short sysstty_15
  4809                              <1> ;		; only the owner can clear its video page
  4810                              <1> ;	xor	al, al ; 0
  4811                              <1> ;@@:
  4812                              <1> ;	;mov	bl, cl		
  4813                              <1> ;	shr	bl, 1 
  4814                              <1> 
  4815 00003A02 30C0                <1> 	xor	al, al	; 0
  4816 00003A04 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4817                              <1> 
  4818                              <1> 	; scroll_up input:
  4819                              <1> 	;
  4820                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4821                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4822                              <1> 	; ah = attribute to be used on blanked line
  4823                              <1> 	; bl = video page number (0 to 7)
  4824                              <1> 
  4825 00003A06 E826DBFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4826                              <1> 
  4827                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4828                              <1> 
  4829                              <1> 	; bl = video page number (0 to 7)
  4830                              <1> 	;xor	dx, dx ; column 0, row 0
  4831                              <1> 	; 02/02/2022
  4832 00003A0B 31D2                <1> 	xor	edx, edx
  4833                              <1> 	; 23/02/2022
  4834                              <1> 	;call	set_cpos
  4835                              <1> 	;retn
  4836 00003A0D E999DAFFFF          <1> 	jmp	set_cpos
  4837                              <1> 
  4838                              <1> 	;mov	al, bl
  4839                              <1> 	;mov	ah, [u.uno]
  4840                              <1> 	;mov	[u.r0], ax
  4841                              <1> 	;jmp	short sysstty_11
  4842                              <1> 
  4843                              <1> ;sysstty_15:
  4844                              <1> ;	; 30/01/2022
  4845                              <1> ;	; permission (denied) error
  4846                              <1> ;	;xor	dl, dl ; sysstty call sign
  4847                              <1> ;	mov	al, cl
  4848                              <1> ;	sub	ah, ah ; 0
  4849                              <1> ;	call	cttyp
  4850                              <1> ;	jmp	error
  4851                              <1> 
  4852                              <1> ; Original UNIX v1 'sysstty' routine:
  4853                              <1> ; gtty:
  4854                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4855                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4856                              <1> 	; 		/ r2 has source
  4857                              <1>         ;mov    r2,-(sp)
  4858                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4859                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4860                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4861                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4862                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4863                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4864                              <1>         ;       br .+4 / list empty, skip branch
  4865                              <1>         ;br     1b / get another character until list is empty
  4866                              <1>         ;mov    0b,r1 / move cc offset to r1
  4867                              <1>         ;inc    r1 / bump it for output clist
  4868                              <1>         ;tstb   cc(r1) / is it 0
  4869                              <1>         ;beq    1f / yes, no characters to output
  4870                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4871                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4872                              <1>         ;br     1b / try to calm it down again
  4873                              <1> ;1:
  4874                              <1>         ;mov    (sp)+,r1
  4875                              <1>         ;mov    (sp)+,r2 / restore registers
  4876                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4877                              <1>         ;beq    1f / if 0, 1f
  4878                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4879                              <1>         ;                   / control status register
  4880                              <1> ;1:
  4881                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4882                              <1>         ;beq    1f / if 0 1f
  4883                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4884                              <1> 	;		    / control status reg
  4885                              <1> ;1:
  4886                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4887                              <1>         ;jmp     sysret2 / return to user
  4888                              <1> 
  4889                              <1> sysgtty: ; < get tty status >
  4890                              <1> 	; 22/02/2022
  4891                              <1> 	; 21/02/2022 
  4892                              <1> 	;	(Retro UNIX 386 v1.2, inode number modifications)
  4893                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4894                              <1> 	;	    ((32 bit reg push/pop))
  4895                              <1> 	; 23/11/2015
  4896                              <1> 	; 29/10/2015
  4897                              <1> 	; 17/10/2015
  4898                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4899                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4900                              <1> 	;
  4901                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4902                              <1> 	; It stores in the three words addressed by it's argument
  4903                              <1> 	; the status of the typewriter whose file descriptor
  4904                              <1> 	; in (u.r0).
  4905                              <1> 	;
  4906                              <1> 	; Calling sequence:
  4907                              <1> 	;	sysgtty; arg
  4908                              <1> 	; Arguments:
  4909                              <1> 	;	arg - address of 3 words destination of the status
  4910                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4911                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4912                              <1> 	; ...............................................................
  4913                              <1> 	;	
  4914                              <1> 	; Retro UNIX 8086 v1 modification: 
  4915                              <1> 	;	'sysgtty' system call will return status of tty
  4916                              <1> 	;	(keyboard, serial port and video page status)
  4917                              <1> 	;	 in following manner:
  4918                              <1> 	;
  4919                              <1> 	; Inputs:
  4920                              <1> 	;	BX = 0 --> means 
  4921                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4922                              <1> 	;	                 for (current) process
  4923                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4924                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4925                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4926                              <1> 	;	     CH > 0 -->	tty number + 1
  4927                              <1> 	;
  4928                              <1> 	;	BX > 0 --> points to name of tty
  4929                              <1> 	;	     CL = 0 --> return keyboard status
  4930                              <1> 	;	     CL = 1 --> return video page status
  4931                              <1> 	;	     CH = undefined		 
  4932                              <1> 	;
  4933                              <1> 	; Outputs:
  4934                              <1> 	;	cf = 0 ->
  4935                              <1> 	;
  4936                              <1> 	;	     AL = tty number from 0 to 9
  4937                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4938                              <1> 	;	     AH = 0 if the tty is free/unused
  4939                              <1> 	;	     AH = the process number of the caller 
  4940                              <1>  	;	     AH = FFh if the tty is locked by another process
  4941                              <1> 	;
  4942                              <1> 	;	  (if calling is for serial port status)
  4943                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4944                              <1> 	;		  (BH = modem status, BL = Line status)
  4945                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4946                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4947                              <1> 	;
  4948                              <1> 	;	  (if calling is for keyboard status)
  4949                              <1> 	;	     BX = current character in tty/keyboard buffer
  4950                              <1> 	;		  (BH = scan code, BL = ascii code)
  4951                              <1> 	;		  (BX=0 if there is not a waiting character)
  4952                              <1> 	;	     CX  is undefined
  4953                              <1> 	;
  4954                              <1> 	;	  (if calling is for video page status)	
  4955                              <1> 	;	     BX = cursor position on the video page
  4956                              <1> 	;		  if tty number < 8
  4957                              <1> 	;		  (BH = row, BL = column)
  4958                              <1> 	;	     CX = current character (in cursor position)
  4959                              <1> 	;		  on the video page of the tty 
  4960                              <1> 	;		  if tty number < 8
  4961                              <1> 	;		  (CH = color, CL = character)
  4962                              <1> 	;	
  4963                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4964                              <1> 	;
  4965                              <1> 	;	     AH = FFh if the caller is not owner of
  4966                              <1> 	;		  specified tty or console tty
  4967                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4968                              <1> 	;	     BX, CX are undefined if cf = 1
  4969                              <1> 	;
  4970                              <1> 	;	  (If tty number is 8 or 9)
  4971                              <1> 	;	     AL = tty number 
  4972                              <1> 	;	     AH = the process number of the caller 
  4973                              <1> 	;	     BX = serial port status
  4974                              <1> 	;  		 (BH = modem status, BL = Line status)
  4975                              <1> 	;	     CX = 0
  4976                              <1> 	;
  4977                              <1> 		
  4978                              <1> gtty:   ; get (requested) tty number
  4979                              <1> 	; 22/02/2022
  4980                              <1> 	; 21/02/2022 (Retro UNIX 386 v1.2, inode number modifications)
  4981                              <1> 	; 17/10/2015
  4982                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4983                              <1> 	; 30/05/2013 - 12/07/2014
  4984                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4985                              <1> 	;
  4986                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4987                              <1> 	;
  4988                              <1> 	; 28/06/2015 (32 bit modifications)
  4989                              <1> 	; 16/01/2014
  4990 00003A12 31C0                <1> 	xor 	eax, eax
  4991 00003A14 6648                <1> 	dec	ax ; 17/10/2015
  4992 00003A16 A3[646D0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4993 00003A1B 80F901              <1> 	cmp	cl, 1
  4994 00003A1E 760F                <1> 	jna	short sysgtty_0
  4995                              <1> sysgtty_invp:
  4996                              <1> 	; 28/06/2015
  4997 00003A20 C705[D86D0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4997 00003A28 0000                <1>
  4998 00003A2A E93EF8FFFF          <1> 	jmp	error
  4999                              <1> sysgtty_0:	
  5000 00003A2F 21DB                <1> 	and	ebx, ebx
  5001 00003A31 7427                <1> 	jz	short sysgtty_1
  5002                              <1> 	;
  5003 00003A33 891D[806D0000]      <1> 	mov	[u.namep], ebx
  5004                              <1> 	;push	cx ; 23/11/2015
  5005 00003A39 51                  <1> 	push	ecx ; 24/12/2021
  5006 00003A3A E846070000          <1> 	call	namei
  5007 00003A3F 59                  <1> 	pop	ecx
  5008                              <1> 	;pop	cx ; 23/11/2015
  5009 00003A40 7213                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  5010                              <1> 	;
  5011                              <1> 	; 21/02/2022
  5012                              <1> 	;cmp	ax, 1
  5013                              <1> 	;jna	short sysgtty_2
  5014                              <1> 	;sub	ax, 10
  5015                              <1> 	;cmp	ax, 9
  5016                              <1> 	;;ja	short sysgtty_inv_dn
  5017                              <1> 	;;mov	ch, al
  5018                              <1> 	;;jmp	short sysgtty_4
  5019                              <1> 	;; 23/11/2015
  5020                              <1> 	;jna	short sysgtty_4
  5021                              <1> 	;
  5022                              <1> 	; 21/02/2022
  5023                              <1> 	; (Retro UNIX 386 v2 file system inode numbers)
  5024 00003A42 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  5025 00003A45 770E                <1> 	ja	short sysgtty_inv_dn
  5026                              <1> 	;cmp	al, 8	; /dev/tty inode number is 8
  5027                              <1> 	;jb	short sysgtty_inv_dn
  5028 00003A47 2C08                <1> 	sub	al, 8
  5029 00003A49 720A                <1> 	jb	short sysgtty_inv_dn
  5030 00003A4B 7416                <1> 	jz	short sysgtty_2 ; /dev/tty inode number is 8
  5031                              <1> 	; convert inode number to tty number (tty0 to tty9)
  5032 00003A4D 2C09                <1> 	sub	al, 9
  5033 00003A4F 7204                <1> 	jb	short sysgtty_inv_dn
  5034                              <1> 	; al = 0 to 9
  5035 00003A51 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  5036 00003A53 EB1F                <1> 	jmp	short sysgtty_4
  5037                              <1> 	
  5038                              <1> sysgtty_inv_dn: 
  5039                              <1> 	;; 28/06/2015
  5040                              <1> 	;; Invalid device name (not a tty) ! error
  5041                              <1> 	;; (Device is not a tty or device name not found)
  5042                              <1> 	;mov	dword [u.error], ERR_INV_DEV_NAME
  5043                              <1> 	;jmp	error
  5044                              <1> 	; 21/02/2022
  5045 00003A55 E935FFFFFF          <1> 	jmp	sysstty_inv_dn
  5046                              <1> 
  5047                              <1> sysgtty_1:
  5048                              <1> 	; 16/01/2014
  5049 00003A5A 80FD0A              <1> 	cmp	ch, 10
  5050 00003A5D 77C1                <1> 	ja	short sysgtty_invp ; 28/06/2015
  5051 00003A5F FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  5052 00003A61 790F                <1> 	jns	short sysgtty_3 ; not negative
  5053                              <1> sysgtty_2:
  5054                              <1> 	; get tty number of console tty
  5055 00003A63 8A25[B56D0000]      <1> 	mov	ah, [u.uno]
  5056                              <1>  	; 28/06/2015
  5057 00003A69 0FB6DC              <1> 	movzx 	ebx, ah
  5058 00003A6C 8AAB[63690000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  5059                              <1> sysgtty_3:
  5060 00003A72 88E8                <1> 	mov	al, ch
  5061                              <1> sysgtty_4:
  5062 00003A74 A2[646D0000]        <1> 	mov	[u.r0], al
  5063                              <1>  	; 28/06/2015
  5064                              <1> 	;cmp	al, 9
  5065                              <1> 	;ja	short sysgtty_invp
  5066 00003A79 8B2D[606D0000]      <1> 	mov	ebp, [u.usp]
  5067                              <1> 	; 23/11/2015
  5068 00003A7F 20C9                <1> 	and	cl, cl
  5069 00003A81 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  5070 00003A83 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  5071 00003A85 722E                <1> 	jb	short sysgtty_6 ; video page status
  5072                              <1> 	; serial port status
  5073                              <1> 	; 12/07/2014
  5074                              <1> 	;mov	dx, 0
  5075                              <1> 	;je	short sysgtty_5
  5076                              <1> 	;inc	dl
  5077                              <1> ;sysgtty_5:
  5078                              <1> 	; 28/06/2015
  5079 00003A87 2C08                <1> 	sub	al, 8
  5080 00003A89 E81AF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  5081                              <1> 	; AL = Line status, AH = Modem status
  5082 00003A8E 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  5083 00003A92 8A25[B56D0000]      <1> 	mov	ah, [u.uno]
  5084 00003A98 8825[656D0000]      <1>         mov     [u.r0+1], ah
  5085                              <1> 	; 24/12/2021
  5086 00003A9E 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  5087                              <1> 				; (in ECX)
  5088 00003AA4 A880                <1> 	test	al, 80h
  5089 00003AA6 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  5090 00003AA8 A801                <1> 	test	al, 1
  5091                              <1> 	;jz	sysret
  5092 00003AAA 7404                <1> 	jz	short sysgtty_10
  5093 00003AAC 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  5094                              <1> sysgtty_10:
  5095 00003AB0 E9D8F7FFFF          <1> 	jmp	sysret
  5096                              <1> sysgtty_6:
  5097 00003AB5 A2[996D0000]        <1> 	mov	[u.ttyn], al ; tty number
  5098                              <1> 	;movzx	ebx, al
  5099 00003ABA 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  5100 00003ABC D0E3                <1> 	shl 	bl, 1  ; aligned to word
  5101                              <1> 	; 22/04/2014 - 29/06/2015
  5102 00003ABE 81C3[74680000]      <1>         add     ebx, ttyl
  5103 00003AC4 8A23                <1>  	mov	ah, [ebx]
  5104 00003AC6 3A25[B56D0000]      <1> 	cmp	ah, [u.uno]
  5105 00003ACC 7404                <1> 	je	short sysgtty_7
  5106 00003ACE 20E4                <1> 	and	ah, ah
  5107                              <1> 	;jz	short sysgtty_7
  5108 00003AD0 7506                <1> 	jnz	short sysgtty_8
  5109                              <1> 	;mov	ah, 0FFh
  5110                              <1> sysgtty_7:
  5111 00003AD2 8825[656D0000]      <1>         mov     [u.r0+1], ah
  5112                              <1> sysgtty_8:
  5113 00003AD8 08C9                <1> 	or	cl, cl
  5114 00003ADA 7510                <1> 	jnz	short sysgtty_9
  5115 00003ADC B001                <1> 	mov	al, 1  ; test a key is available
  5116 00003ADE E884210000          <1> 	call	getc
  5117 00003AE3 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  5118 00003AE7 E9A1F7FFFF          <1> 	jmp	sysret
  5119                              <1> sysgtty_9:
  5120 00003AEC 8A1D[996D0000]      <1> 	mov	bl, [u.ttyn]
  5121                              <1> 	; bl = video page number
  5122 00003AF2 E8E1220000          <1> 	call 	get_cpos
  5123                              <1> 	; dx = cursor position
  5124 00003AF7 66895510            <1> 	mov	[ebp+16], dx ; bx
  5125                              <1> 	;mov	bl, [u.ttyn]
  5126                              <1> 	; bl = video page number
  5127 00003AFB E8E9220000          <1> 	call	read_ac_current
  5128                              <1> 	; ax = character and attribute/color
  5129 00003B00 66894518            <1> 	mov	[ebp+24], ax ; cx
  5130 00003B04 E984F7FFFF          <1> 	jmp	sysret
  5131                              <1> sysgtty_dnr_err:
  5132                              <1> 	; 'device not responding !' error	
  5133                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  5134 00003B09 C705[D86D0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  5134 00003B11 0000                <1>
  5135 00003B13 E955F7FFFF          <1> 	jmp	error	
  5136                              <1> 
  5137                              <1> ; Original UNIX v1 'sysgtty' routine:
  5138                              <1> ; sysgtty:
  5139                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  5140                              <1> 	;	       / r2 has destination
  5141                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  5142                              <1> 	;                     / in 1st word of dest
  5143                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  5144                              <1> 	;                     / in 2nd word of dest
  5145                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  5146                              <1>         ;jmp    sysret2 / return to user
  5147                              <1> 	
  5148                              <1> ; Original UNIX v1 'gtty' routine:
  5149                              <1> ; gtty:
  5150                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  5151                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  5152                              <1>         ;jsr    r0,getf / get the i-number of the file
  5153                              <1>         ;tst    r1 / is it open for reading
  5154                              <1>         ;bgt    1f / yes
  5155                              <1>         ;neg    r1 / no, i-number is negative, 
  5156                              <1> 	;          / so make it positive
  5157                              <1> ;1:
  5158                              <1>         ;sub    $14.,r1 / get i-number of tty0
  5159                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  5160                              <1>         ;bhis   error9 / no, error
  5161                              <1>         ;asl    r1 / 0%2
  5162                              <1>         ;asl    r1 / 0%4 / yes
  5163                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  5164                              <1> 	;	       ; / tty block
  5165                              <1>         ;mov    u.off,r2 / put argument in r2
  5166                              <1>         ;rts    r0 / return
  2088                                  %include 'u2.s'      ; 11/05/2015
  2089                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2090                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2091                              <1> ; ****************************************************************************
  2092                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.1) - SYS2.INC
  2093                              <1> ; Last Modification: 15/05/2022
  2094                              <1> ; ----------------------------------------------------------------------------
  2095                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2096                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2097                              <1> ;
  2098                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2099                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2100                              <1> ; <Bell Laboratories (17/3/1972)>
  2101                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2102                              <1> ;
  2103                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2104                              <1> ;
  2105                              <1> ; ****************************************************************************
  2106                              <1> 
  2107                              <1> syslink:
  2108                              <1> 	; 12/01/2022
  2109                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2110                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2111                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2112                              <1> 	;
  2113                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2114                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2115                              <1> 	; given to the entry that will go in the current directory.
  2116                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2117                              <1> 	; in the name 2 entry of current directory is the same
  2118                              <1> 	; i-number for the name 1 file.
  2119                              <1> 	;
  2120                              <1> 	; Calling sequence:
  2121                              <1> 	;	syslink; name 1; name 2
  2122                              <1> 	; Arguments:
  2123                              <1> 	;	name 1 - file name to which link will be created.
  2124                              <1> 	;	name 2 - name of entry in current directory that
  2125                              <1> 	;		 links to name 1.
  2126                              <1> 	; Inputs: -
  2127                              <1> 	; Outputs: -
  2128                              <1> 	; ...............................................................
  2129                              <1> 	;	
  2130                              <1> 	; Retro UNIX 8086 v1 modification: 
  2131                              <1> 	;       'syslink' system call has two arguments; so,
  2132                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2133                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2134                              <1> 	;
  2135                              <1> 		; / name1, name2
  2136                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2137 00003B18 891D[806D0000]      <1> 	mov	[u.namep], ebx
  2138 00003B1E 51                  <1> 	push	ecx
  2139 00003B1F E861060000          <1> 	call	namei
  2140                              <1> 		; jsr r0,namei / find the i-number associated with
  2141                              <1> 			     ; / the 1st path name
  2142                              <1>      	;;and	ax, ax
  2143                              <1> 	;;jz	error ; File not found
  2144                              <1> 	;jc	error 
  2145                              <1> 		; br error9 / cannot be found
  2146 00003B24 730F                <1> 	jnc	short syslink0
  2147                              <1> 	;pop 	ecx
  2148                              <1> 	; 'file not found !' error
  2149 00003B26 C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2149 00003B2E 0000                <1>
  2150 00003B30 E938F7FFFF          <1> 	jmp	error
  2151                              <1> syslink0:
  2152 00003B35 E84B110000          <1> 	call	iget
  2153                              <1> 		; jsr r0,iget / get the i-node into core
  2154 00003B3A 8F05[806D0000]      <1> 	pop	dword [u.namep] ; ecx
  2155                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2156                              <1> 	; 24/12/2021
  2157 00003B40 50                  <1> 	push	eax ; *
  2158                              <1> 	;push	ax
  2159                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2160                              <1> 			    ; / (a link to this file is to be created)
  2161                              <1> 	; 24/12/2021
  2162 00003B41 8A0D[416D0000]      <1> 	mov	cl, [cdev]
  2163 00003B47 51                  <1> 	push	ecx ; **
  2164                              <1> 	;push	word [cdev]
  2165                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2166 00003B48 E8AC000000          <1> 	call	isdir
  2167                              <1> 		; jsr r0,isdir / is it a directory
  2168 00003B4D E833060000          <1> 	call	namei
  2169                              <1> 		; jsr r0,namei / no, get i-number of name2
  2170                              <1> 	;jnc	error
  2171                              <1> 		; br .+4   / not found 
  2172                              <1> 			 ; / so r1 = i-number of current directory
  2173                              <1> 			 ; / ii = i-number of current directory
  2174                              <1> 		; br error9 / file already exists., error
  2175 00003B52 720F                <1> 	jc	short syslink1
  2176                              <1> 	; pop eax ; 24/12/2021
  2177                              <1> 	; pop eax
  2178                              <1> 	; 'file exists !' error
  2179 00003B54 C705[D86D0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2179 00003B5C 0000                <1>
  2180 00003B5E E90AF7FFFF          <1> 	jmp	error
  2181                              <1> syslink1:
  2182                              <1> 	;pop	cx
  2183                              <1> 	; 24/12/2021
  2184 00003B63 59                  <1> 	pop	ecx ; **
  2185                              <1> 	;cmp	cx, [cdev]
  2186 00003B64 3A0D[416D0000]      <1> 	cmp	cl, [cdev]
  2187                              <1> 	;jne	error
  2188                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2189                              <1> 			       ; / end of current directory
  2190                              <1> 	        ; bne error9
  2191 00003B6A 740F                <1> 	je	short syslink2
  2192                              <1> 	; 'not same drive !' error
  2193 00003B6C C705[D86D0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2193 00003B74 0000                <1>
  2194 00003B76 E9F2F6FFFF          <1> 	jmp	error
  2195                              <1> syslink2:
  2196                              <1> 	;pop	eax ; 24/12/2021
  2197                              <1> 	;push	eax
  2198                              <1> 	; 24/12/2021
  2199 00003B7B 8B0424              <1> 	mov	eax, [esp] ; *
  2200 00003B7E 66A3[9C6D0000]      <1> 	mov	[u.dirbuf], ax
  2201                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2202 00003B84 E8C5000000          <1> 	call	mkdir
  2203                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2204                              <1> 		 	     ; / in current directory
  2205                              <1> 	; 24/12/2021
  2206 00003B89 58                  <1> 	pop	eax ; *
  2207                              <1> 	;pop	ax
  2208                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2209 00003B8A E8F6100000          <1> 	call	iget
  2210                              <1> 		; jsr r0,iget / get i-node into core
  2211 00003B8F FE05[E6680000]      <1> 	inc	byte [i.nlks]
  2212                              <1> 		; incb i.nlks / add 1 to its number of links
  2213                              <1> sysunlink_2:
  2214                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2215 00003B95 C605[556D0000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  2216                              <1> 				;  but inode's itself has been modified)
  2217 00003B9C E875120000          <1> 	call	setimod
  2218                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2219 00003BA1 E9E7F6FFFF          <1> 	jmp	sysret
  2220                              <1> 
  2221                              <1> sysunlink:
  2222                              <1> 	; 12/01/2022
  2223                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2224                              <1> 	; 04/12/2015 (14 byte file names)
  2225                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2226                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2227                              <1> 	;
  2228                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2229                              <1> 	; name from its directory. If this entry was the last link
  2230                              <1> 	; to the file, the contents of the file are freed and the
  2231                              <1> 	; file is destroyed. If, however, the file was open in any
  2232                              <1> 	; process, the actual destruction is delayed until it is 
  2233                              <1> 	; closed, even though the directory entry has disappeared.
  2234                              <1> 	; 
  2235                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2236                              <1> 	; does not exist or that its directory can not be written.
  2237                              <1> 	; Write permission is not required on the file itself.
  2238                              <1> 	; It is also illegal to unlink a directory (except for
  2239                              <1> 	; the superuser).
  2240                              <1> 	;
  2241                              <1> 	; Calling sequence:
  2242                              <1> 	;	sysunlink; name
  2243                              <1> 	; Arguments:
  2244                              <1> 	;	name - name of directory entry to be removed 
  2245                              <1> 	; Inputs: -
  2246                              <1> 	; Outputs: -
  2247                              <1> 	; ...............................................................
  2248                              <1> 	;				
  2249                              <1> 	; Retro UNIX 8086 v1 modification:
  2250                              <1> 	;	 The user/application program puts address of the name
  2251                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2252                              <1> 
  2253                              <1> 	; / name - remove link name
  2254 00003BA6 891D[806D0000]      <1> 	mov	[u.namep], ebx
  2255                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2256 00003BAC E8D4050000          <1> 	call	namei
  2257                              <1> 		; jsr r0,namei / find the i-number associated 
  2258                              <1> 			     ; / with the path name
  2259                              <1> 	;jc	error
  2260                              <1> 		; br error9 / not found
  2261 00003BB1 730F                <1> 	jnc	short sysunlink1
  2262                              <1> 	; 'file not found !' error
  2263 00003BB3 C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2263 00003BBB 0000                <1>
  2264 00003BBD E9ABF6FFFF          <1> 	jmp	error
  2265                              <1> sysunlink1:
  2266 00003BC2 50                  <1> 	push	eax ; 24/12/2021
  2267                              <1> 	;push	ax
  2268                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2269 00003BC3 E831000000          <1> 	call	isdir
  2270                              <1> 		; jsr r0,isdir / is it a directory
  2271                              <1> 	;xor 	ax, ax
  2272                              <1> 	; 24/12/2021
  2273 00003BC8 31C0                <1> 	xor	eax, eax
  2274 00003BCA 66A3[9C6D0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2275                              <1> 		; clr u.dirbuf / no, clear the location that will
  2276                              <1> 			   ; / get written into the i-number portion
  2277                              <1> 			 ; / of the entry
  2278 00003BD0 832D[846D0000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2279                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2280 00003BD7 E8BD000000          <1> 	call	wdir
  2281                              <1> 		; jsr r0,wdir / free the directory entry
  2282 00003BDC 58                  <1> 	pop	eax ; 24/12/2021
  2283                              <1> 	;pop	ax
  2284                              <1> 		; mov (sp)+,r1 / get i-number back
  2285 00003BDD E8A3100000          <1> 	call	iget
  2286                              <1> 		; jsr r0,iget / get i-node
  2287                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2288                              <1> 	;call	setimod
  2289                              <1> 	;	; jsr r0,setimod / set modified flag
  2290                              <1> 	;	
  2291 00003BE2 FE0D[E6680000]      <1> 	dec	byte [i.nlks]
  2292                              <1> 		; decb i.nlks / decrement the number of links
  2293                              <1> 	; 24/12/2021
  2294 00003BE8 75AB                <1> 	jnz	short sysunlink_2
  2295                              <1> 	;jnz	sysret
  2296                              <1> 		; bgt sysret9 / if this was not the last link
  2297                              <1> 			    ; / to file return
  2298                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2299 00003BEA E827120000          <1> 	call	setimod
  2300                              <1> 		; jsr r0,setimod / set modified flag
  2301                              <1> 	; AX = r1 = i-number
  2302 00003BEF E89D0A0000          <1> 	call	anyi
  2303                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2304                              <1> 			 ; / Then free contents of file and destroy it.
  2305 00003BF4 E994F6FFFF          <1> 	jmp	sysret
  2306                              <1> 		; br sysret9
  2307                              <1> ;sysunlink_2:
  2308                              <1> 	;; 12/01/2022 - Retro UNIX 386 v1.2
  2309                              <1> 	;mov	byte [imodx], 1	; (flag means file data is same
  2310                              <1> 	;			;  but inode's itself has been modified)
  2311                              <1> 	;call	setimod
  2312                              <1> 	;	; jsr r0,setimod / set the i-node modified flag
  2313                              <1> 	;jmp	sysret
  2314                              <1> 
  2315                              <1> isdir:
  2316                              <1> 	; 13/03/2022
  2317                              <1> 	; 08/01/2022
  2318                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  2319                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2320                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2321                              <1> 	;
  2322                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2323                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2324                              <1> 	;  called by syslink and sysunlink to make sure directories
  2325                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2326                              <1> 	; 'isdir' does not bother checking. The current i-node
  2327                              <1> 	;  is not disturbed.			
  2328                              <1> 	;		
  2329                              <1> 	; INPUTS ->
  2330                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2331                              <1> 	;    u.uid - user id
  2332                              <1> 	; OUTPUTS ->
  2333                              <1> 	;    r1 - contains current i-number upon exit
  2334                              <1> 	;    	 (current i-node back in core) 
  2335                              <1> 	;	
  2336                              <1> 	; ((AX = R1))
  2337                              <1> 	;
  2338                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2339                              <1> 	;
  2340                              <1> 
  2341                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2342                              <1> 	; / there is an error unless super user made the call
  2343                              <1> 	
  2344                              <1> 	; 01/01/2022
  2345 00003BF9 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit uid (runix v2 fs inode)
  2346                              <1> 	;cmp	byte [u.uid], 0 
  2347                              <1> 		; tstb u.uid / super user
  2348 00003C01 764A                <1> 	jna	short isdir1
  2349                              <1> 		; beq 1f / yes, don't care
  2350                              <1> 	; 08/01/2022
  2351 00003C03 FF35[3C6D0000]      <1> 	push	dword [ii]
  2352                              <1> 	;push	word [ii]
  2353                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2354 00003C09 E877100000          <1> 	call	iget
  2355                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2356                              <1> 	; 01/01/2022 (runix v2 fs inode flags)
  2357 00003C0E F605[E5680000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  2358 00003C15 7421                <1> 	jz	short isdir2 ; no, error!
  2359 00003C17 F605[E5680000]40    <1> 	test	byte [i.flgs+1], 40h ; directory flag
  2360                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2361                              <1> 		; bit $40000,i.flgs / is it a directory
  2362                              <1> 	;jnz	error
  2363                              <1> 		; bne error9 / yes, error
  2364 00003C1E 7427                <1> 	jz	short isdir0
  2365                              <1> 
  2366                              <1> 	; 13/03/2022
  2367                              <1> 	; NOTE:
  2368                              <1> 	; Unix v5-v7 kernels do not allow (ordinary) users
  2369                              <1> 	; (except root/superuser) --if [u.uid] > 0--
  2370                              <1> 	; to link a directory. (ref: sys2.c, 'link')
  2371                              <1> 	;
  2372                              <1> 	; But, Retro UNIX 386 v1.2 will allow the owner of
  2373                              <1> 	; the directory to link it.
  2374                              <1> 
  2375 00003C20 66A1[E8680000]      <1> 	mov	ax, [i.uid] ; owner ID of the parent dir
  2376 00003C26 663B05[B66D0000]    <1> 	cmp	ax, [u.uid] ; user ID of current user/process
  2377 00003C2D 7509                <1> 	jne	short isdir2
  2378                              <1> 	; 13/03/2022
  2379                              <1> 	; additional checking (may or may not be necessary!?)
  2380 00003C2F 663B05[B86D0000]    <1> 	cmp	ax, [u.ruid] 
  2381                              <1> 			; real (login) user ID must be same
  2382 00003C36 740F                <1> 	je	short isdir0
  2383                              <1> 
  2384                              <1> isdir2:
  2385 00003C38 C705[D86D0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2385 00003C40 0000                <1>
  2386                              <1> 				; 'permission denied !' error
  2387                              <1> 	;pop	ax
  2388 00003C42 E926F6FFFF          <1> 	jmp	error	
  2389                              <1> isdir0:	
  2390                              <1> 	; 08/01/2022
  2391 00003C47 58                  <1> 	pop	eax
  2392                              <1> 	;pop	ax
  2393                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2394 00003C48 E838100000          <1> 	call	iget
  2395                              <1> 		; jsr r0,iget / get it back in
  2396                              <1> isdir1: ; 1:
  2397 00003C4D C3                  <1> 	retn
  2398                              <1> 		; rts r0
  2399                              <1> 
  2400                              <1> mkdir:
  2401                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2402                              <1> 	; 04/12/2015 (14 byte directory names)
  2403                              <1> 	; 12/10/2015
  2404                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2405                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2406                              <1> 	;
  2407                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2408                              <1> 	; by u.namep into the current directory.
  2409                              <1> 	;
  2410                              <1> 	; INPUTS ->
  2411                              <1> 	;    u.namep - points to a file name 
  2412                              <1> 	;	           that is about to be a directory entry.
  2413                              <1> 	;    ii - current directory's i-number.	
  2414                              <1> 	; OUTPUTS ->
  2415                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2416                              <1> 	;    u.off - points to entry to be filled 
  2417                              <1> 	;	     in the current directory		
  2418                              <1> 	;    u.base - points to start of u.dirbuf.
  2419                              <1> 	;    r1 - contains i-number of current directory 
  2420                              <1> 	;	
  2421                              <1> 	; ((AX = R1)) output
  2422                              <1> 	;
  2423                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2424                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2425                              <1> 	;
  2426                              <1> 
  2427                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2428 00003C4E 31C0                <1> 	xor 	eax, eax
  2429 00003C50 BF[9E6D0000]        <1> 	mov     edi, u.dirbuf+2
  2430 00003C55 89FE                <1> 	mov	esi, edi
  2431 00003C57 AB                  <1> 	stosd
  2432 00003C58 AB                  <1> 	stosd
  2433                              <1> 	; 04/12/2015 (14 byte directory names)
  2434 00003C59 AB                  <1> 	stosd
  2435 00003C5A 66AB                <1> 	stosw
  2436                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2437 00003C5C 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2438                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2439                              <1> 	;mov 	ebp, [u.namep]
  2440 00003C5E E881060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2441                              <1> 		; esi = physical address (page start + offset)
  2442                              <1> 		; ecx = byte count in the page (1 - 4096)
  2443                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2444                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2445                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2446                              <1> mkdir_1: ; 1: 
  2447 00003C63 45                  <1> 	inc	ebp ; 12/10/2015
  2448                              <1> 	;
  2449                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2450                              <1> 	; 01/08/2013
  2451 00003C64 AC                  <1> 	lodsb
  2452                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2453 00003C65 20C0                <1> 	and 	al, al
  2454 00003C67 7426                <1> 	jz 	short mkdir_3 	  
  2455                              <1> 		; beq 1f / if null, done
  2456 00003C69 3C2F                <1> 	cmp	al, '/'
  2457                              <1> 		; cmp r1,$'/ / is it a "/"?
  2458 00003C6B 7413                <1> 	je	short mkdir_err
  2459                              <1> 	;je	error
  2460                              <1> 		; beq error9 / yes, error
  2461                              <1> 	; 12/10/2015
  2462                              <1> 	;dec	cx
  2463 00003C6D 49                  <1> 	dec	ecx ; 24/12/2021
  2464 00003C6E 7505                <1> 	jnz	short mkdir_2
  2465                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2466 00003C70 E875060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2467                              <1> 		; esi = physical address (page start + offset)
  2468                              <1> 		; ecx = byte count in the page
  2469                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2470                              <1> mkdir_2:
  2471 00003C75 81FF[AC6D0000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2472                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2473                              <1> 				     ; / a char?
  2474 00003C7B 74E6                <1> 	je	short mkdir_1
  2475                              <1> 		; beq 1b / yes, go back
  2476 00003C7D AA                  <1> 	stosb
  2477                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2478 00003C7E EBE3                <1> 	jmp 	short mkdir_1
  2479                              <1> 		; br 1b / get next char
  2480                              <1> mkdir_err:
  2481                              <1> 	; 17/06/2015
  2482 00003C80 C705[D86D0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2482 00003C88 0000                <1>
  2483 00003C8A E9DEF5FFFF          <1> 	jmp	error
  2484                              <1> 
  2485                              <1> mkdir_3: ; 1:
  2486 00003C8F A1[7C6D0000]        <1> 	mov	eax, [u.dirp]
  2487 00003C94 A3[846D0000]        <1> 	mov	[u.off], eax
  2488                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2489                              <1> 				 ; / slot to u.off
  2490                              <1> 	; 08/01/2022
  2491                              <1> wdir:	; 24/12/2021 (Retro UNIX 386 v1.2)
  2492                              <1> 	; 29/04/2013
  2493 00003C99 C705[886D0000]-     <1>         mov     dword [u.base], u.dirbuf
  2493 00003C9F [9C6D0000]          <1>
  2494                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2495 00003CA3 C705[8C6D0000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2495 00003CAB 0000                <1>
  2496                              <1> 		; mov $10.,u.count / u.count = 10
  2497                              <1> 	; 08/01/2022
  2498 00003CAD A1[3C6D0000]        <1> 	mov	eax, [ii]
  2499                              <1> 	;mov	ax, [ii] 
  2500                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2501                              <1> 	;mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2502                              <1> 	; 08/01/2022 (Retro UNIX 386 v2 file system inode)
  2503 00003CB2 66BA8000            <1> 	mov	dx, 80h	; mov dx, IWRITE
  2504 00003CB6 E8B4100000          <1> 	call 	access
  2505                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2506                              <1> 				 ; / for writing
  2507                              <1> 	; AX = i-number of current directory
  2508                              <1> 	; 01/08/2013
  2509 00003CBB FE05[D66D0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2510                              <1> 	;call	writei
  2511                              <1> 	;	; jsr r0,writei / write into directory
  2512                              <1> 	;retn	
  2513                              <1> 	;	; rts r0
  2514                              <1> 	; 24/12/2021
  2515 00003CC1 E93B150000          <1> 	jmp	writei
  2516                              <1> 
  2517                              <1> 
  2518                              <1> 	; 09/05/2022 
  2519                              <1> 	;	(Retro UNIX 386 v1.2, Kernel v0.2.2.1)
  2520                              <1> 	; 06/02/2022
  2521                              <1> 	; 12/01/2022
  2522                              <1> 	; 01/01/2022
  2523                              <1> 	; 24/12/2021
  2524                              <1> 	; 11/12/2021
  2525                              <1> 	; 04/12/2021
  2526                              <1> 	; 30/11/2021
  2527                              <1> 	; 28/11/2021 - Retro UNIX 386 v1.2
  2528                              <1> 	;	(Retro UNIX 386 v2 fs compatibility modification)
  2529                              <1> sysexec:
  2530                              <1> 	; 02/05/2021
  2531                              <1> 	; 27/03/2021
  2532                              <1> 	; 26/03/2021
  2533                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  2534                              <1> 	; 23/10/2015
  2535                              <1> 	; 10/10/2015, 18/10/2015, 19/10/2015
  2536                              <1> 	; 29/07/2015, 05/08/2015, 05/08/2015
  2537                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2538                              <1> 	; 01/07/2015, 02/07/2015, 20/07,2015
  2539                              <1> 	; 24/06/2015, 25/06/2021
  2540                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2541                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2542                              <1> 	;
  2543                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2544                              <1> 	; pointed to by 'name' in the sysexec call. 
  2545                              <1> 	; 'sysexec' performs the following operations:
  2546                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2547                              <1> 	;    2. obtains i-node of file to be executed via 'iget'.
  2548                              <1> 	;    3. sets trap vectors to system routines.
  2549                              <1> 	;    4. loads arguments to be passed to executing file into
  2550                              <1> 	;	highest locations of user's core
  2551                              <1> 	;    5. puts pointers to arguments in locations immediately
  2552                              <1> 	;	following arguments.
  2553                              <1> 	;    6.	saves number of arguments in next location.
  2554                              <1> 	;    7. initializes user's stack area so that all registers
  2555                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2556                              <1> 	;	to core when 'sysret' restores registers 
  2557                              <1> 	;	and does an rti.
  2558                              <1> 	;    8. inializes u.r0 and u.sp
  2559                              <1> 	;    9. zeros user's core down to u.r0
  2560                              <1> 	;   10.	reads executable file from storage device into core
  2561                              <1> 	;	starting at location 'core'.
  2562                              <1> 	;   11.	sets u.break to point to end of user's code with
  2563                              <1> 	;	data area appended.
  2564                              <1> 	;   12.	calls 'sysret' which returns control at location
  2565                              <1> 	;	'core' via 'rti' instruction.
  2566                              <1> 	;
  2567                              <1> 	; Calling sequence:
  2568                              <1> 	;	sysexec; namep; argp
  2569                              <1> 	; Arguments:
  2570                              <1> 	;	namep - points to pathname of file to be executed
  2571                              <1> 	;	argp  - address of table of argument pointers
  2572                              <1> 	;	argp1... argpn - table of argument pointers
  2573                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2574                              <1> 	; Inputs: (arguments)
  2575                              <1> 	; Outputs: -	
  2576                              <1> 	; ...............................................................
  2577                              <1> 	;
  2578                              <1> 	; Retro UNIX 386 v1 modification: 
  2579                              <1> 	;	User application runs in it's own virtual space 
  2580                              <1> 	;	which is izolated from kernel memory (and other
  2581                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2582                              <1> 	;	privilige mode. Virtual start address is always 0.
  2583                              <1> 	;	User's core memory starts at linear address 400000h
  2584                              <1> 	;	(the end of the 1st 4MB).
  2585                              <1> 	;
  2586                              <1> 	; Retro UNIX 8086 v1 modification: 
  2587                              <1> 	;	user/application segment and system/kernel segment
  2588                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2589                              <1> 	;	are different (user's registers are saved to 
  2590                              <1> 	;	and then restored from system's stack.)
  2591                              <1> 	;
  2592                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2593                              <1> 	;	      arguments which were in these registers;
  2594                              <1> 	;	      but, it returns by putting the 1st argument
  2595                              <1> 	;	      in 'u.namep' and the 2nd argument
  2596                              <1> 	;	      on top of stack. (1st argument is offset of the
  2597                              <1> 	;	      file/path name in the user's program segment.)
  2598                              <1> 	
  2599                              <1> 	;call	arg2
  2600                              <1> 	; * name - 'u.namep' points to address of file/path name
  2601                              <1> 	;          in the user's program segment ('u.segmnt')
  2602                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2603                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2604                              <1> 	;          which is on top of stack.
  2605                              <1> 	;
  2606                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2607                              <1> 
  2608                              <1> 	; 23/06/2015 (32 bit modifications)
  2609                              <1> 
  2610 00003CC6 891D[806D0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2611                              <1>         ; 18/10/2015
  2612 00003CCC 890D[F46D0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2613 00003CD2 E8AE040000          <1> 	call	namei
  2614                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2615                              <1> 			     ; / named in sysexec call in r1
  2616                              <1> 	;jc	error
  2617                              <1> 		; br error9
  2618 00003CD7 730F                <1> 	jnc	short sysexec_0
  2619                              <1> 	;
  2620                              <1> 	; 'file not found !' error
  2621 00003CD9 C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2621 00003CE1 0000                <1>
  2622 00003CE3 E985F5FFFF          <1> 	jmp	error
  2623                              <1> 
  2624                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2625                              <1> 	; (executable file flag is checked in 'access')
  2626                              <1> 	; (following error message is in 'access' subroutine)
  2627                              <1> ;sysexec_not_exf:
  2628                              <1> 	;; 'not executable file !' error
  2629                              <1> 	;mov	dword [u.error], ERR_NOT_EXECUTABLE
  2630                              <1> 	;jmp	error 
  2631                              <1> sysexec_0:
  2632                              <1> 	; 26/03/2021 ('iget' will be called in 'access')
  2633                              <1> 	;call	iget
  2634                              <1> 	;	; jsr r0,iget / get i-node for file to be executed
  2635                              <1> 	;
  2636                              <1> 	;test	byte [i.flgs], 10h
  2637                              <1> 	;;test	word [i.flgs], 10h
  2638                              <1> 	;	; bit $20,i.flgs / is file executable
  2639                              <1> 	;jz	short sysexec_not_exf
  2640                              <1> 	;;jz	error
  2641                              <1> 	;	; beq error9
  2642                              <1> 	; 26/03/2021
  2643 00003CE8 66BA4000            <1> 	mov	dx, 40h ; IEXEC - execute, owner
  2644 00003CEC E87E100000          <1> 	call	access
  2645                              <1> 	; ! we are here because there is execute permission !
  2646                              <1> 	; ('iopen' is not needed for regular files, from now on)
  2647                              <1> 
  2648                              <1> 	; 26/03/2021
  2649                              <1> 	;; 25/03/2021
  2650                              <1> 	;; (ref: Retro UNIX 386 v2, 'ux.s')
  2651                              <1> 	;mov	dx, 40h ; IEXEC - execute, owner
  2652                              <1> 	;;
  2653                              <1> 	;call	iopen
  2654                              <1> 	;	; jsr r0,iopen / gets i-node for file with i-number
  2655                              <1> 	;		     ; / given in r1 (opens file)
  2656                              <1> 	
  2657                              <1> 	; 26/03/2021
  2658                              <1> 	; AX = i-number of the file
  2659                              <1> 	;test	byte [i.flgs], 20h
  2660                              <1> 	;;test	word [i.flgs], 20h
  2661                              <1> 	;	; bit $40,i.flgs / test user id on execution bit
  2662                              <1> 	;jz	short sysexec_1
  2663                              <1> 	;	; beq 1f
  2664                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013
  2665                              <1> 	;	; tstb u.uid / test user id
  2666                              <1> 	;jna	short sysexec_1
  2667                              <1> 	;	; beq 1f / super user
  2668                              <1> 
  2669                              <1> 	;mov	cl, [i.uid]
  2670                              <1> 	;mov	[u.uid], cl ; 02/08/2013
  2671                              <1> 	;	; movb i.uid,u.uid / put user id of owner of file
  2672                              <1> 				 ; / as process user id
  2673                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2674                              <1> 	;mov	al, [i.flgs+1]
  2675 00003CF1 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0	; super user (root) ?
  2676                              <1> 	;jna	short sysexec_19 ; yes, super user
  2677                              <1> 	;; 02/05/2021
  2678 00003CF9 7625                <1> 	jna	short sysexec_1	; don't set UID or GID
  2679                              <1> 
  2680                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2
  2681 00003CFB A0[E5680000]        <1> 	mov	al, [i.flgs+1]
  2682                              <1> 
  2683                              <1> 	; test set user id on execution bit 
  2684 00003D00 A808                <1> 	test	al, 08h ; ISUID flag (800h)
  2685                              <1> 	;jz	short sysexec_19
  2686                              <1> 	; 02/05/2021
  2687 00003D02 741C                <1> 	jz	short sysexec_1 ; do not set group ID
  2688                              <1> 				; (if user ID will not be set)
  2689                              <1> 				; (02/05/2021)	
  2690                              <1> 	; set user id on exec (800h)
  2691                              <1> 	; 26/03/2021
  2692                              <1> sysexec_setuid:
  2693                              <1> 	;; 27/03/2021
  2694                              <1> 	;cmp	word [u.uid], 0
  2695                              <1> 	;;jna	short sysexec_19 ; super user
  2696                              <1> 	;; 02/05/2021
  2697                              <1> 	;jna	short sysexec_1 ; do not set group ID
  2698                              <1> 	;			; (if user ID will not be set)
  2699                              <1> 	;			; (02/05/2021)
  2700 00003D04 668B0D[E8680000]    <1> 	mov	cx, [i.uid]
  2701 00003D0B 66890D[B66D0000]    <1> 	mov	[u.uid], cx
  2702                              <1> sysexec_19:
  2703                              <1> 	; test set group id on execution bit 
  2704 00003D12 A804                <1> 	test	al, 04h ; ISGID flag (400h)
  2705 00003D14 740A                <1> 	jz	short sysexec_1
  2706                              <1> sysexec_setgid:
  2707                              <1> 	; set group id on exec (400h)
  2708 00003D16 A0[EA680000]        <1> 	mov	al, [i.gid]
  2709 00003D1B A2[BA6D0000]        <1> 	mov	[u.gid], al
  2710                              <1> 	;
  2711                              <1> sysexec_1:
  2712                              <1> 	; 06/02/2022
  2713                              <1> 	; 12/01/2022
  2714                              <1> 	; 24/12/2021
  2715                              <1> 	; 11/12/2021
  2716                              <1> 	; 04/12/2021
  2717                              <1> 	; 10/10/2015, 18/10/2015
  2718                              <1> 	; 21/07/2015, 24/07/2015
  2719                              <1> 	; 24/06/2015, 25/06/2015
  2720                              <1>         ; Moving arguments to the end of [u.upage]
  2721                              <1> 	; (by regarding page borders in user's memory space)
  2722                              <1> 	;
  2723                              <1> 	; 10/10/2015
  2724                              <1> 	; 21/07/2015
  2725 00003D20 89E5                <1> 	mov	ebp, esp ; (**)
  2726                              <1> 	; 18/10/2015
  2727 00003D22 89EF                <1> 	mov 	edi, ebp
  2728 00003D24 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2729                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2730 00003D29 29CF                <1> 	sub	edi, ecx
  2731 00003D2B 89FC                <1> 	mov	esp, edi
  2732 00003D2D 31C0                <1> 	xor	eax, eax
  2733 00003D2F A3[906D0000]        <1> 	mov 	[u.nread], eax ; 0
  2734                              <1> 	; 12/01/2022
  2735                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2736                              <1> 	; may leave it with any value after an error))
  2737 00003D34 A3[F06D0000]        <1> 	mov	[argc], eax ; 0
  2738                              <1> 	;
  2739 00003D39 49                  <1> 	dec	ecx ; 256 - 1
  2740 00003D3A 890D[8C6D0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2741                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2742                              <1> 	; 24/12/2021
  2743                              <1> sysexec_2:
  2744 00003D40 8B35[F46D0000]      <1> 	mov	esi, [argv] ; 18/10/2015
  2745 00003D46 E85C020000          <1> 	call	get_argp
  2746                              <1> 	;mov	ecx, 4 
  2747                              <1> 	; 06/02/2022
  2748 00003D4B 31C9                <1> 	xor	ecx, ecx
  2749 00003D4D B104                <1> 	mov	cl, 4
  2750                              <1> sysexec_3:
  2751 00003D4F 21C0                <1> 	and	eax, eax
  2752 00003D51 7454                <1> 	jz	short sysexec_6
  2753                              <1> 	; 18/10/2015
  2754 00003D53 010D[F46D0000]      <1> 	add	[argv], ecx ; 4
  2755                              <1> 	;;inc	word [argc]
  2756                              <1> 	; 11/12/2021
  2757                              <1> 	;inc	dword [argc]
  2758                              <1> 	; 12/01/2022
  2759 00003D59 FE05[F06D0000]      <1> 	inc	byte [argc]
  2760                              <1> 	;
  2761 00003D5F A3[886D0000]        <1> 	mov	[u.base], eax
  2762                              <1>  	; 23/10/2015
  2763 00003D64 66C705[D06D0000]00- <1> 	mov	word [u.pcount], 0
  2763 00003D6C 00                  <1>
  2764                              <1> sysexec_4:
  2765 00003D6D E8BF160000          <1> 	call	cpass ; get a character from user's core memory
  2766 00003D72 750B                <1>         jnz	short sysexec_5
  2767                              <1> 		; (max. 255 chars + null)
  2768                              <1> 	; 18/10/2015
  2769 00003D74 28C0                <1> 	sub 	al, al
  2770 00003D76 AA                  <1> 	stosb
  2771 00003D77 FF05[906D0000]      <1> 	inc	dword [u.nread]
  2772 00003D7D EB28                <1> 	jmp	short sysexec_6
  2773                              <1> sysexec_5:
  2774 00003D7F AA                  <1> 	stosb
  2775 00003D80 20C0                <1> 	and 	al, al
  2776 00003D82 75E9                <1> 	jnz	short sysexec_4
  2777 00003D84 B904000000          <1> 	mov	ecx, 4
  2778 00003D89 390D[EC6D0000]      <1> 	cmp	[ncount], ecx ; 4
  2779 00003D8F 72AF                <1> 	jb	short sysexec_2
  2780 00003D91 8B35[E86D0000]      <1> 	mov	esi, [nbase]
  2781 00003D97 010D[E86D0000]      <1> 	add	[nbase], ecx ; 4	
  2782                              <1> 	;sub	[ncount], cx 
  2783                              <1> 	; 11/12/2021
  2784 00003D9D 290D[EC6D0000]      <1> 	sub	[ncount], ecx
  2785 00003DA3 8B06                <1> 	mov	eax, [esi]
  2786 00003DA5 EBA8                <1> 	jmp	short sysexec_3
  2787                              <1> sysexec_6:
  2788                              <1> 	; 24/12/2021
  2789                              <1> 	; 18/10/2015
  2790                              <1> 	; argument list transfer from user's core memory to
  2791                              <1> 	; kernel stack frame is OK here.
  2792                              <1> 	; [u.nread] = argument list length
  2793                              <1> 	;mov	[argv], esp ; start address of argument list
  2794                              <1> 	;
  2795                              <1> 	; 18/10/2015
  2796                              <1> 	; 24/07/2015
  2797                              <1>         ; 21/07/2015
  2798                              <1> 	; 02/07/2015
  2799                              <1> 	; 25/06/2015
  2800                              <1> 	; 24/06/2015
  2801                              <1> 	; 23/06/2015
  2802                              <1> 	;
  2803 00003DA7 8B1D[C86D0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2804 00003DAD 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2805 00003DAF 740A                <1> 	jz	short sysexec_7
  2806 00003DB1 A1[C46D0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2807 00003DB6 E859E8FFFF          <1> 	call	deallocate_page_dir
  2808                              <1> sysexec_7:
  2809 00003DBB E889E7FFFF          <1> 	call	make_page_dir
  2810                              <1> 	;jc	short sysexec_14
  2811                              <1> 	;jc	panic  ; allocation error 
  2812                              <1> 	;	       ; after a deallocation would be nonsence !?
  2813                              <1> 	; 26/03/2021
  2814 00003DC0 7243                <1> 	jc	short sysexec_panic
  2815                              <1> 	
  2816                              <1> 	; 24/07/2015
  2817                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2818                              <1> 	;     of the user's page directory
  2819                              <1> 	;     (It is needed for interrupts!)
  2820                              <1> 	; 18/10/2015
  2821 00003DC2 8B15[28680000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2822 00003DC8 8B02                <1> 	mov	eax, [edx] ; physical address of
  2823                              <1> 			   ; kernel's first page table (1st 4 MB)
  2824                              <1> 			   ; (PDE 0 of kernel's page directory)
  2825 00003DCA 8B15[C46D0000]      <1> 	mov 	edx, [u.pgdir]
  2826 00003DD0 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2827                              <1> 	;
  2828                              <1> 	; 20/07/2015
  2829 00003DD2 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2830                              <1> 	; 18/10/2015
  2831 00003DD7 BE[E06D0000]        <1> 	mov	esi, pcore ; physical start address
  2832                              <1> sysexec_8:	
  2833 00003DDC B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2834 00003DE1 E881E7FFFF          <1> 	call	make_page_table
  2835                              <1> 	;jc	panic
  2836                              <1> 	; 26/03/2021
  2837 00003DE6 721D                <1> 	jc	short sysexec_panic
  2838                              <1> 	;
  2839                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2840 00003DE8 E888E7FFFF          <1> 	call	make_page ; make new page, clear and set the pte
  2841                              <1> 	;jc	panic
  2842                              <1> 	; 26/03/2021
  2843 00003DED 7216                <1> 	jc	short sysexec_panic
  2844                              <1> 	;
  2845 00003DEF 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2846                              <1> 	; ebx = virtual address (24/07/2015)
  2847                              <1> 	; 30/11/2021
  2848                              <1> 	;call 	add_to_swap_queue
  2849                              <1> 	; 18/10/2015
  2850 00003DF1 81FE[E46D0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2851 00003DF7 7411                <1> 	je	short sysexec_9 ; yes
  2852 00003DF9 BE[E46D0000]        <1> 	mov	esi, ecore  ; physical address of the last page
  2853                              <1> 	; 20/07/2015
  2854 00003DFE BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2855                              <1> 	; ebx = virtual end address + segment base address - 4K
  2856 00003E03 EBD7                <1>         jmp     short sysexec_8
  2857                              <1> sysexec_panic:
  2858                              <1> 	; 26/03/2021
  2859 00003E05 E9AAECFFFF          <1> 	jmp	panic
  2860                              <1> 
  2861                              <1> sysexec_9:
  2862                              <1> 	; 12/01/2022
  2863                              <1> 	; 11/12/2021
  2864                              <1> 	; 18/10/2015
  2865                              <1> 	; 26/08/2015
  2866                              <1> 	; 25/06/2015
  2867                              <1> 	; move arguments from kernel stack to [ecore]
  2868                              <1> 	; (argument list/line will be copied from kernel stack
  2869                              <1> 	; frame to the last (stack) page of user's core memory)
  2870                              <1> 	; 18/10/2015
  2871 00003E0A 8B3D[E46D0000]      <1> 	mov	edi, [ecore]
  2872 00003E10 81C700100000        <1> 	add	edi, PAGE_SIZE
  2873                              <1> 	;movzx	eax, word [argc]
  2874                              <1> 	; 12/01/2022
  2875                              <1> 	;xor	eax, eax
  2876                              <1> 	;mov	al, [argc]
  2877                              <1> 	; [argc] < 32
  2878                              <1> 	; 11/12/2021
  2879 00003E16 A1[F06D0000]        <1> 	mov	eax, [argc]
  2880 00003E1B 09C0                <1> 	or	eax, eax
  2881 00003E1D 7509                <1> 	jnz	short sysexec_10
  2882 00003E1F 89FB                <1> 	mov 	ebx, edi
  2883 00003E21 83EB04              <1> 	sub	ebx, 4 
  2884 00003E24 8903                <1> 	mov	[ebx], eax ; 0
  2885 00003E26 EB43                <1> 	jmp 	short sysexec_13
  2886                              <1> sysexec_10:
  2887 00003E28 8B0D[906D0000]      <1> 	mov	ecx, [u.nread]
  2888                              <1> 	;mov 	esi, [argv]
  2889 00003E2E 89E6                <1> 	mov	esi, esp ; start address of argument list
  2890 00003E30 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2891                              <1> 
  2892                              <1> 	;;;;
  2893                              <1> 	; 09/05/2022
  2894                              <1> 	; (move edi -backward- to dword boundary)
  2895                              <1> 	; ((this will prevent 'general protection fault' error
  2896                              <1> 	;  as result of a lodsd or dword move instruction
  2897                              <1> 	;  at the end of argument list))
  2898 00003E32 83EF03              <1> 	sub	edi, 3
  2899 00003E35 83E7FC              <1> 	and	edi, ~3 ; (*)
  2900                              <1> 	;;;
  2901                              <1> 
  2902 00003E38 89C2                <1> 	mov	edx, eax
  2903                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2904 00003E3A FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2905 00003E3C C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2906                              <1> 	; edx <= 128
  2907 00003E3F 89FB                <1> 	mov	ebx, edi
  2908                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2909                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2910 00003E41 29D3                <1> 	sub 	ebx, edx
  2911 00003E43 89FA                <1> 	mov	edx, edi
  2912 00003E45 F3A4                <1> 	rep	movsb
  2913 00003E47 89D6                <1> 	mov 	esi, edx
  2914 00003E49 89DF                <1> 	mov 	edi, ebx
  2915 00003E4B BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2916 00003E50 2B15[E46D0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2917 00003E56 AB                  <1> 	stosd	; eax = argument count
  2918                              <1> sysexec_11:
  2919 00003E57 89F0                <1> 	mov	eax, esi
  2920 00003E59 01D0                <1> 	add	eax, edx
  2921 00003E5B AB                  <1> 	stosd  ; eax = virtual address
  2922 00003E5C FE0D[F06D0000]      <1> 	dec	byte [argc]
  2923 00003E62 7407                <1> 	jz	short sysexec_13
  2924                              <1> sysexec_12:
  2925 00003E64 AC                  <1> 	lodsb
  2926 00003E65 20C0                <1> 	and	al, al
  2927 00003E67 75FB                <1> 	jnz	short sysexec_12
  2928 00003E69 EBEC                <1> 	jmp	short sysexec_11
  2929                              <1> 	;
  2930                              <1> 	; 1:
  2931                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2932                              <1> 			     ; / pointers to arguments to be passed
  2933                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2934                              <1> 			      ; / u.quit = 1 take quit
  2935                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2936                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2937                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2938                              <1> 			       ; / system routine
  2939                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector
  2940                              <1> 			       ; / set to take system routine
  2941                              <1> 		; mov $sstack,sp / stack space used during swapping
  2942                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2943                              <1> 		; mov $ecore,r5 / r5 has end of core
  2944                              <1> 		; mov $core,r4 / r4 has start of users core
  2945                              <1> 		; mov r4,u.base / u.base has start of users core
  2946                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2947                              <1> 	; 1:
  2948                              <1> 		; tst (r2)+ / argument char = "nul"
  2949                              <1> 		; bne 1b
  2950                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of
  2951                              <1> 			  ; / end of argument pointer list
  2952                              <1> 	; 1:
  2953                              <1> 	     ; / move arguments to bottom of users core
  2954                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2955                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2956                              <1> 			    ; / ptr list
  2957                              <1> 		; blo 1f / branch to 1f when all arguments
  2958                              <1> 		       ; / are moved
  2959                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2960                              <1> 	; 2:
  2961                              <1> 		; tstb (r3)+
  2962                              <1> 		; bne 2b / scan argument for \0 (nul)
  2963                              <1> 
  2964                              <1> 	; 2:
  2965                              <1> 		; movb -(r3),-(r5) / move argument char 
  2966                              <1> 				 ; / by char starting at "ecore"
  2967                              <1> 		; cmp r3,(r2) / moved all characters in 
  2968                              <1> 			    ; / this argument
  2969                              <1> 		; bhi 2b / branch 2b if not
  2970                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2971                              <1> 			     ; / r5 has pointer to nth arg
  2972                              <1> 		; br 1b / string
  2973                              <1> 	; 1:
  2974                              <1> 		; clrb -(r5)
  2975                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2976                              <1> 			; / last word of argument strings
  2977                              <1> 		; mov $core,r2
  2978                              <1> 	
  2979                              <1> 	; 1: / move argument pointers into core following 
  2980                              <1> 	      ; / argument strings
  2981                              <1> 		; cmp r2,r4
  2982                              <1> 		; bhis 1f / branch to 1f when all pointers
  2983                              <1> 			; / are moved
  2984                              <1> 		; mov (r2)+,-(r5)
  2985                              <1> 		; br 1b
  2986                              <1> 	; 1:
  2987                              <1> 		; sub $core,r4 / gives number of arguments *2
  2988                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2989                              <1> 		       ; / the number of args stored
  2990                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2991                              <1> 			     ; / of the argument pointers
  2992                              <1> sysexec_13:
  2993                              <1> 	; 30/11/2021
  2994                              <1> 	; 28/11/2021
  2995                              <1> 	; 19/10/2015
  2996                              <1> 	; 18/10/2015
  2997                              <1> 	; 29/07/2015
  2998                              <1> 	; 25/07/2015
  2999                              <1> 	; 24/07/2015
  3000                              <1> 	; 20/07/2015
  3001                              <1> 	; 25/06/2015
  3002                              <1> 	; 24/06/2015
  3003                              <1> 	; 23/06/2015
  3004                              <1> 	;
  3005                              <1> 	; moving arguments to [ecore] is OK here..
  3006                              <1> 	; 18/10/2015
  3007 00003E6B 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  3008                              <1> 	; ebx = beginning address of argument list pointers
  3009                              <1> 	;	in user's stack
  3010                              <1> 	; 19/10/2015
  3011 00003E6D 2B1D[E46D0000]      <1> 	sub 	ebx, [ecore]
  3012 00003E73 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  3013                              <1> 			; end of core - 4096 (last page)
  3014                              <1> 			; (virtual address)
  3015 00003E79 891D[F46D0000]      <1> 	mov	[argv], ebx
  3016 00003E7F 891D[946D0000]      <1> 	mov	[u.break], ebx ; available user memory
  3017                              <1> 	;
  3018 00003E85 29C0                <1> 	sub	eax, eax
  3019 00003E87 C705[8C6D0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  3019 00003E8F 0000                <1>
  3020                              <1> 		; mov $14,u.count
  3021 00003E91 C705[786D0000]-     <1> 	mov	dword [u.fofp], u.off
  3021 00003E97 [846D0000]          <1>
  3022                              <1> 		; mov $u.off,u.fofp
  3023 00003E9B A3[846D0000]        <1> 	mov	[u.off], eax ; 0
  3024                              <1> 		; clr u.off / set offset in file to be read to zero
  3025                              <1> 	; 25/07/2015
  3026 00003EA0 A3[886D0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  3027                              <1> 	; 25/06/2015 
  3028 00003EA5 A1[3C6D0000]        <1> 	mov	eax, [ii] ; 28/11/2021 (32 bit inode number)
  3029                              <1> 	; AX = i-number of the executable file
  3030 00003EAA E842110000          <1> 	call	readi
  3031                              <1> 		; jsr r0,readi / read in first six words of 
  3032                              <1> 			; / user's file, starting at $core
  3033                              <1> 		; mov sp,r5 / put users stack address in r5
  3034                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  3035                              <1> 				; / from r5 (leaves number of words
  3036                              <1> 				; / less 26 available for
  3037                              <1> 			     	; / program in user core
  3038                              <1> 		; mov r5,u.count /
  3039                              <1> 	; 25/06/2015
  3040 00003EAF 8B0D[946D0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  3041 00003EB5 890D[8C6D0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  3042                              <1> 	;
  3043 00003EBB 8B0D[906D0000]      <1> 	mov	ecx, [u.nread]
  3044 00003EC1 890D[946D0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  3045 00003EC7 80F920              <1> 	cmp	cl, 32
  3046 00003ECA 7540                <1>         jne     short sysexec_15
  3047                              <1> 	;:
  3048                              <1> 	; 25/06/2015
  3049                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  3050                              <1> 	; 18/10/2015
  3051 00003ECC 8B35[E06D0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  3052                              <1> 		             ; (phys. start addr. of the exec. file)
  3053 00003ED2 AD                  <1> 	lodsd
  3054 00003ED3 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  3055 00003ED7 7533                <1> 	jne	short sysexec_15
  3056                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  3057                              <1> 			      ; / if file is standard a.out format
  3058                              <1> 		; bne 1f / branch, if not standard format
  3059 00003ED9 AD                  <1> 	lodsd
  3060 00003EDA 89C1                <1> 	mov	ecx, eax ; text (code) section size
  3061 00003EDC AD                  <1> 	lodsd
  3062 00003EDD 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  3063                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  3064                              <1> 		              ; / number of bytes in program text
  3065                              <1> 		; sub $14,r5 / subtract 12
  3066 00003EDF 89CB                <1> 	mov	ebx, ecx
  3067                              <1> 	;
  3068                              <1> 	; 25/06/2015
  3069                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  3070                              <1> 	;	and SINGLIX operating systems (as code template).
  3071                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  3072                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  3073                              <1> 	;	Overrun is not possible for current version.
  3074                              <1> 	;
  3075 00003EE1 AD                  <1> 	lodsd	
  3076 00003EE2 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  3077 00003EE4 3B1D[8C6D0000]      <1> 	cmp	ebx, [u.count]
  3078 00003EEA 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  3079                              <1> 	;
  3080                              <1> 	; 24/07/2015
  3081                              <1> 	; add bss section size to [u.break]
  3082 00003EEC 0105[946D0000]      <1> 	add 	[u.break], eax
  3083                              <1> 	;
  3084 00003EF2 83E920              <1> 	sub	ecx, 32 ; header size (already loaded)
  3085                              <1> 	;cmp	ecx, [u.count]
  3086                              <1> 	;jnb	short sysexec_16
  3087                              <1> 		; cmp r5,u.count /
  3088                              <1> 		; bgt 1f / branch if r5 greater than u.count
  3089 00003EF5 890D[8C6D0000]      <1> 	mov	[u.count], ecx ; required read count
  3090                              <1> 		; mov r5,u.count
  3091                              <1> 	;
  3092 00003EFB EB29                <1> 	jmp	short sysexec_16
  3093                              <1> 	;
  3094                              <1> sysexec_14:
  3095                              <1> 	; 23/06/2015
  3096                              <1> 	; insufficient (out of) memory
  3097 00003EFD C705[D86D0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  3097 00003F05 0000                <1>
  3098 00003F07 E961F3FFFF          <1> 	jmp	error
  3099                              <1> 	;
  3100                              <1> sysexec_15:
  3101                              <1> 	; 25/06/2015
  3102                              <1>         ;movzx   edx, word [i.size] ; file size
  3103                              <1> 	; 30/11/2021
  3104 00003F0C 8B15[EC680000]      <1> 	mov	edx, [i.size] ; file size
  3105 00003F12 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  3106 00003F14 7626                <1> 	jna	short sysexec_17 ; no need to next read
  3107 00003F16 01D1                <1> 	add	ecx, edx ; [i.size]
  3108 00003F18 3B0D[8C6D0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  3109 00003F1E 77DD                <1> 	ja	short sysexec_14
  3110 00003F20 8915[8C6D0000]      <1> 	mov	[u.count], edx
  3111                              <1> sysexec_16:
  3112                              <1> 	;mov	ax, [ii] ; i-number
  3113                              <1> 	; 28/11/2021
  3114 00003F26 A1[3C6D0000]        <1> 	mov	eax, [ii] ; 32 bit inode number
  3115 00003F2B E8C1100000          <1> 	call	readi
  3116                              <1> 		; add core+10,u.nread / add size of user data area
  3117                              <1> 		                    ; / to u.nread
  3118                              <1> 		; br 2f
  3119                              <1> 	; 1:
  3120                              <1> 		; jsr r0,readi / read in rest of file
  3121                              <1> 	; 2:
  3122 00003F30 8B0D[906D0000]      <1> 	mov	ecx, [u.nread]
  3123 00003F36 010D[946D0000]      <1> 	add	[u.break], ecx
  3124                              <1> 		; mov u.nread,u.break / set users program break to end of
  3125                              <1> 				    ; / user code
  3126                              <1> 		; add $core+14,u.break / plus data area
  3127                              <1> 	; 20/07/2015
  3128                              <1> sysexec_17:
  3129                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  3130                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3131                              <1> 	;;mov	ax, [ii] ; i-number
  3132                              <1> 	;call	iclose
  3133                              <1> 	;	; jsr r0,iclose / does nothing
  3134 00003F3C 31C0                <1>         xor     eax, eax
  3135 00003F3E FEC0                <1> 	inc	al
  3136 00003F40 66A3[B06D0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3137 00003F46 66A3[B26D0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3138                              <1> 	; 30/11/2021
  3139 00003F4C FEC8                <1> 	dec	al  ; eax = 0
  3140                              <1> 	; 02/07/2015
  3141                              <1>         ;cmp	dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ?
  3142 00003F4E 3905[C86D0000]      <1> 	cmp	[u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ?
  3143 00003F54 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3144                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3145 00003F56 8B15[28680000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3146 00003F5C 8915[C86D0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here
  3147                              <1> sysexec_18:
  3148                              <1> 	; 18/10/2015
  3149                              <1> 	; 05/08/2015
  3150                              <1> 	; 29/07/2015
  3151 00003F62 8B2D[F46D0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must points to argument
  3152                              <1> 			    ; list pointers (argument count)
  3153 00003F68 FA                  <1> 	cli
  3154 00003F69 8B25[C4670000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3155                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3156                              <1> 			    ; for this process	 
  3157                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3158                              <1> 	;;xor	eax, eax ; 0
  3159                              <1> 	;dec	al ; eax = 0
  3160                              <1> 	; eax = 0 ; 30/11/2021 
  3161 00003F6F 66BA2300            <1> 	mov	dx, UDATA
  3162 00003F73 6652                <1> 	push	dx  ; user's stack segment
  3163 00003F75 55                  <1> 	push	ebp ; user's stack pointer
  3164                              <1> 		    ; (points to number of arguments)
  3165 00003F76 FB                  <1> 	sti
  3166 00003F77 9C                  <1> 	pushfd	; EFLAGS
  3167                              <1> 		; Set IF for enabling interrupts in user mode
  3168                              <1> 	;or	dword [esp], 200h 
  3169                              <1> 	;
  3170                              <1> 	;mov	bx, UCODE
  3171                              <1> 	;push	bx ; user's code segment
  3172 00003F78 6A1B                <1> 	push	UCODE
  3173                              <1> 	;push	0
  3174 00003F7A 50                  <1> 	push	eax ; EIP (=0) - start address -
  3175                              <1> 		; clr -(r5) / popped into ps when rti in 
  3176                              <1> 			  ; / sysrele is executed
  3177                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3178                              <1> 		                ; / in sysrele is executed
  3179                              <1> 		;mov r5,0f / load second copyz argument
  3180                              <1> 		;tst -(r5) / decrement r5
  3181 00003F7B 8925[5C6D0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3182                              <1> 	; 05/08/2015
  3183                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3184                              <1> 	; ('push dx' would cause to general protection fault, 
  3185                              <1> 	; after 'pop ds' etc.)
  3186                              <1> 	;
  3187                              <1> 	;; push dx ; ds (UDATA)
  3188                              <1> 	;; push dx ; es (UDATA)
  3189                              <1> 	;; push dx ; fs (UDATA)
  3190                              <1> 	;; push dx ; gs (UDATA)
  3191                              <1> 	;
  3192                              <1> 	; This is a trick to prevent general protection fault
  3193                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3194 00003F81 8EC2                <1> 	mov 	es, dx ; UDATA
  3195 00003F83 06                  <1> 	push 	es ; ds (UDATA)
  3196 00003F84 06                  <1> 	push 	es ; es (UDATA)
  3197 00003F85 06                  <1> 	push 	es ; fs (UDATA)
  3198 00003F86 06                  <1> 	push	es ; gs (UDATA)
  3199 00003F87 66BA1000            <1> 	mov	dx, KDATA
  3200 00003F8B 8EC2                <1> 	mov	es, dx
  3201                              <1> 	;
  3202                              <1> 	;; pushad simulation
  3203 00003F8D 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3204 00003F8F 50                  <1> 	push	eax ; eax (0)
  3205 00003F90 50                  <1> 	push	eax ; ecx (0)
  3206 00003F91 50                  <1> 	push	eax ; edx (0)
  3207 00003F92 50                  <1> 	push	eax ; ebx (0)
  3208 00003F93 55                  <1> 	push	ebp ; esp before pushad
  3209 00003F94 50                  <1> 	push	eax ; ebp (0)
  3210 00003F95 50                  <1> 	push	eax ; esi (0)		
  3211 00003F96 50                  <1> 	push	eax ; edi (0)	
  3212                              <1> 	;
  3213 00003F97 A3[646D0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3214 00003F9C 8925[606D0000]      <1> 	mov	[u.usp], esp
  3215                              <1> 		; mov r5,u.r0 /
  3216                              <1> 		; sub $16.,r5 / skip 8 words
  3217                              <1> 		; mov r5,u.sp / assign user stack pointer value,
  3218                              <1> 		;             / effectively zeroes all regs
  3219                              <1> 			    ; / when sysrele is executed
  3220                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3221                              <1> 		; clr u.break
  3222                              <1> 		; mov r5,sp / point sp to user's stack
  3223                              <1> 	;
  3224 00003FA2 E9E8F2FFFF          <1> 	jmp	sysret0
  3225                              <1> 	;jmp	sysret
  3226                              <1> 		; br sysret3 / return to core image at $core
  3227                              <1> 
  3228                              <1> get_argp:
  3229                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  3230                              <1> 	; 18/10/2015 (nbase, ncount)
  3231                              <1> 	; 21/07/2015
  3232                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3233                              <1> 	; Get (virtual) address of argument from user's core memory
  3234                              <1> 	;
  3235                              <1> 	; INPUT:
  3236                              <1> 	;	esi = virtual address of argument pointer
  3237                              <1> 	; OUTPUT:
  3238                              <1> 	;	eax = virtual address of argument
  3239                              <1> 	;
  3240                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3241                              <1> 	;
  3242 00003FA7 833D[C86D0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3243                              <1> 				    ; (the caller is kernel)
  3244 00003FAE 767C                <1>         jna     short get_argpk 
  3245                              <1> 	;
  3246 00003FB0 89F3                <1>      	mov	ebx, esi
  3247 00003FB2 E819E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3248 00003FB7 7254                <1>         jc	short get_argp_err ; 11/12/2021
  3249 00003FB9 A3[E86D0000]        <1> 	mov 	[nbase], eax ; physical address	
  3250                              <1> 	;mov	[ncount], cx ; remain byte count in page (1-4096)
  3251                              <1> 	; 11/12/2021
  3252 00003FBE 890D[EC6D0000]      <1> 	mov	[ncount], ecx
  3253 00003FC4 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3254                              <1> 	;cmp	cx, ax ; 4
  3255                              <1> 	; 11/12/2021
  3256 00003FC9 39C1                <1> 	cmp	ecx, eax ; 4
  3257 00003FCB 734A                <1> 	jnb	short get_argp2
  3258 00003FCD 89F3                <1> 	mov	ebx, esi
  3259 00003FCF 01CB                <1> 	add	ebx, ecx
  3260 00003FD1 E8FAE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3261 00003FD6 7235                <1> 	jc	short get_argp_err
  3262                              <1> 	;push	esi
  3263 00003FD8 89C6                <1> 	mov	esi, eax
  3264                              <1> 	;xchg	cx, [ncount]
  3265                              <1> 	; 11/12/2021
  3266 00003FDA 870D[EC6D0000]      <1> 	xchg	ecx, [ncount]
  3267 00003FE0 8735[E86D0000]      <1> 	xchg	esi, [nbase]
  3268 00003FE6 B504                <1> 	mov	ch, 4
  3269 00003FE8 28CD                <1> 	sub	ch, cl
  3270                              <1> get_argp0:
  3271 00003FEA AC                  <1> 	lodsb
  3272                              <1> 	;push	ax
  3273                              <1> 	; 11/12/2021
  3274 00003FEB 50                  <1> 	push	eax
  3275 00003FEC FEC9                <1> 	dec	cl
  3276 00003FEE 75FA                <1>         jnz     short get_argp0
  3277 00003FF0 8B35[E86D0000]      <1> 	mov	esi, [nbase]
  3278                              <1> 	; 21/07/2015
  3279 00003FF6 0FB6C5              <1> 	movzx	eax, ch
  3280 00003FF9 0105[E86D0000]      <1> 	add	[nbase], eax
  3281                              <1> 	;sub	[ncount], ax
  3282                              <1> 	; 11/12/2021
  3283 00003FFF 2905[EC6D0000]      <1> 	sub	[ncount], eax
  3284                              <1> get_argp1:
  3285 00004005 AC                  <1> 	lodsb
  3286 00004006 FECD                <1> 	dec	ch
  3287 00004008 743B                <1>         jz      short get_argp3
  3288                              <1>         ;push	ax
  3289                              <1> 	; 11/12/2021
  3290 0000400A 50                  <1> 	push	eax
  3291 0000400B EBF8                <1> 	jmp     short get_argp1
  3292                              <1> get_argp_err:
  3293 0000400D A3[D86D0000]        <1> 	mov	[u.error], eax
  3294 00004012 E956F2FFFF          <1> 	jmp	error
  3295                              <1> get_argp2:
  3296                              <1> 	; 21/07/2015
  3297                              <1> 	;mov	eax, 4
  3298 00004017 8B15[E86D0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3299 0000401D 0105[E86D0000]      <1> 	add	[nbase], eax
  3300                              <1> 	;sub	[ncount], ax
  3301                              <1> 	; 11/12/2021
  3302 00004023 2905[EC6D0000]      <1> 	sub	[ncount], eax
  3303                              <1> 	;
  3304 00004029 8B02                <1> 	mov	eax, [edx]
  3305 0000402B C3                  <1> 	retn
  3306                              <1> get_argpk:
  3307                              <1> 	; Argument is in kernel's memory space
  3308 0000402C 66C705[EC6D0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3308 00004034 10                  <1>
  3309 00004035 8935[E86D0000]      <1> 	mov	[nbase], esi
  3310 0000403B 8305[E86D0000]04    <1> 	add	dword [nbase], 4
  3311 00004042 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physical addr.
  3312 00004044 C3                  <1> 	retn
  3313                              <1> get_argp3:
  3314 00004045 B103                <1> 	mov	cl, 3
  3315                              <1> get_argp4:
  3316 00004047 C1E008              <1> 	shl	eax, 8
  3317                              <1> 	;pop	dx
  3318                              <1> 	; 11/12/2021
  3319 0000404A 5A                  <1> 	pop	edx
  3320 0000404B 88D0                <1> 	mov 	al, dl
  3321 0000404D E2F8                <1>         loop    get_argp4
  3322                              <1> 	;pop	esi
  3323 0000404F C3                  <1> 	retn	
  3324                              <1> 
  3325                              <1> sysfstat:
  3326                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.1)
  3327                              <1> 	;	([idev] return in eax)
  3328                              <1> 	;	0 = root device
  3329                              <1> 	;	1 = mounted device (>0)
  3330                              <1> 	; 06/02/2022 
  3331                              <1> 	; 08/01/2022
  3332                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3333                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3334                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3335                              <1> 	;
  3336                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3337                              <1> 	; on open files instead of files given by name. It puts the
  3338                              <1> 	; buffer address on the stack, gets the i-number and
  3339                              <1> 	; checks to see if the file is open for reading or writing.
  3340                              <1> 	; If the file is open for writing (i-number is negative)
  3341                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3342                              <1> 	; is made.	
  3343                              <1> 	;
  3344                              <1> 	; Calling sequence:
  3345                              <1> 	;	sysfstat; buf
  3346                              <1> 	; Arguments:
  3347                              <1> 	;	buf - buffer address
  3348                              <1> 	;
  3349                              <1> 	; Inputs: *u.r0 - file descriptor
  3350                              <1> 	; Outputs: buffer is loaded with file information
  3351                              <1> 	; ...............................................................
  3352                              <1> 	;				
  3353                              <1> 	; Retro UNIX 8086 v1 modification:
  3354                              <1> 	;       'sysfstat' system call has two arguments; so,
  3355                              <1> 	;	* 1st argument, file descriptor is in BX register
  3356                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3357                              <1> 
  3358                              <1> 	; / set status of open file
  3359                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3360 00004050 51                  <1> 	push	ecx ; *
  3361                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3362                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3363                              <1> 		; jsr r0,getf / get the files i-number
  3364                              <1> 	; BX = file descriptor (file number)
  3365 00004051 E8F9000000          <1> 	call	getf1
  3366                              <1> 	; 06/02/2022
  3367 00004056 21C0                <1> 	and	eax, eax
  3368                              <1> 	;and	ax, ax ; i-number of the file
  3369                              <1> 		; tst	r1 / is it 0?
  3370                              <1> 	;jz	error
  3371                              <1> 		; beq error3 / yes, error
  3372                              <1> 	;jnz	short sysfstat1
  3373                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system)
  3374 00004058 752C                <1> 	jnz	short sysstat1
  3375 0000405A C705[D86D0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3375 00004062 0000                <1>
  3376 00004064 E904F2FFFF          <1> 	jmp	error
  3377                              <1> 	; 26/12/2021
  3378                              <1> ;sysfstat1:
  3379                              <1> 	;cmp	ah, 80h
  3380                              <1>         ;jb      short sysstat1
  3381                              <1> 	;	; bgt 1f / if i-number is negative (open for writing)
  3382                              <1> 	;neg	ax
  3383                              <1> 	;	; neg r1 / make it positive, then branch
  3384                              <1> 	; 08/01/2022
  3385                              <1> 	;jmp	short sysstat1
  3386                              <1> 		; br 1f / to 1f
  3387                              <1> sysstat:
  3388                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3389                              <1> 	;	([idev] return in eax)
  3390                              <1> 	;	0 = root device
  3391                              <1> 	;	1 = mounted device (>0)
  3392                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3393                              <1> 	; 18/10/2015
  3394                              <1> 	; 07/10/2015
  3395                              <1> 	; 02/09/2015
  3396                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3397                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3398                              <1> 	;
  3399                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3400                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3401                              <1> 	; long and information about the file placed in it.	
  3402                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3403                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3404                              <1> 	; is then loaded and the results are given in the UNIX
  3405                              <1> 	; Programmers Manual sysstat (II).	
  3406                              <1> 	;
  3407                              <1> 	; Calling sequence:
  3408                              <1> 	;	sysstat; name; buf
  3409                              <1> 	; Arguments:
  3410                              <1> 	;	name - points to the name of the file
  3411                              <1> 	;	buf - address of a 34 bytes buffer
  3412                              <1> 	; Inputs: -
  3413                              <1> 	; Outputs: buffer is loaded with file information
  3414                              <1> 	; ...............................................................
  3415                              <1> 	;				
  3416                              <1> 	; Retro UNIX 8086 v1 modification: 
  3417                              <1> 	;       'sysstat' system call has two arguments; so,
  3418                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3419                              <1> 	;	to get sysstat system call arguments from the user;
  3420                              <1> 	;	* 1st argument, name is pointed to by BX register
  3421                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3422                              <1> 	;
  3423                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3424                              <1> 	;	      arguments which were in these registers;
  3425                              <1> 	;	      but, it returns by putting the 1st argument
  3426                              <1> 	;	      in 'u.namep' and the 2nd argument
  3427                              <1> 	;	      on top of stack. (1st argument is offset of the
  3428                              <1> 	;	      file/path name in the user's program segment.)		 	
  3429                              <1> 	
  3430                              <1> 	; / ; name of file; buffer - get files status
  3431                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3432 00004069 891D[806D0000]      <1> 	mov	[u.namep], ebx
  3433 0000406F 51                  <1> 	push	ecx ; *
  3434 00004070 E810010000          <1> 	call	namei
  3435                              <1> 		; jsr r0,namei / get the i-number for the file
  3436                              <1> 	;jc	error
  3437                              <1> 		; br error3 / no such file, error
  3438 00004075 730F                <1> 	jnc	short sysstat1
  3439                              <1> 	; pop 	ecx
  3440                              <1> sysstat_err0:
  3441                              <1> 	; 'file not found !' error
  3442 00004077 C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3442 0000407F 0000                <1>
  3443 00004081 E9E7F1FFFF          <1> 	jmp	error
  3444                              <1> 
  3445                              <1> sysstat1: ; 1:
  3446 00004086 E8FA0B0000          <1> 	call	iget
  3447                              <1> 		; jsr r0,iget / get the i-node into core
  3448                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3449                              <1> 	; 02/09/2015
  3450 0000408B 8F05[886D0000]      <1> 	pop	dword [u.base] ; *
  3451                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3452 00004091 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3453 00004096 730A                <1> 	jnc 	short sysstat2
  3454                              <1> sysstat_err1:
  3455 00004098 A3[D86D0000]        <1> 	mov	dword [u.error], eax ; error code
  3456 0000409D E9CBF1FFFF          <1> 	jmp	error
  3457                              <1> sysstat2:
  3458 000040A2 A0[3C6D0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3459 000040A7 AA                  <1> 	stosb
  3460 000040A8 FF05[886D0000]      <1> 	inc 	dword [u.base]
  3461                              <1> 	;dec 	cx
  3462 000040AE 49                  <1> 	dec	ecx ; 26/12/2021
  3463 000040AF 7505                <1> 	jnz	short sysstat3
  3464 000040B1 E841000000          <1> 	call	sysstat_gpa
  3465                              <1> 	;jc	short sysstat_err1
  3466                              <1> sysstat3:
  3467 000040B6 A0[3D6D0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3468 000040BB AA                  <1> 	stosb
  3469                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3470 000040BC FF05[886D0000]      <1> 	inc 	dword [u.base]
  3471                              <1> 	;;dec 	word [u.pcount]
  3472                              <1> 	;dec	cx
  3473 000040C2 49                  <1> 	dec	ecx ; 26/12/2021
  3474 000040C3 7505                <1> 	jnz	short sysstat4
  3475 000040C5 E82D000000          <1> 	call	sysstat_gpa
  3476                              <1> 	;jc	short sysstat_err1	
  3477                              <1> sysstat4:
  3478 000040CA BE[E4680000]        <1> 	mov	esi, inode
  3479                              <1> 		; mov $inode,r2 / r2 points to i-node
  3480                              <1> sysstat5: ; 1:
  3481 000040CF A4                  <1> 	movsb
  3482                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3483 000040D0 FF05[886D0000]      <1> 	inc 	dword [u.base]
  3484                              <1> 	;;dec 	word [u.pcount]
  3485                              <1> 	;dec	cx
  3486 000040D6 49                  <1> 	dec	ecx ; 26/12/2021
  3487 000040D7 7505                <1> 	jnz	short sysstat6
  3488 000040D9 E819000000          <1> 	call	sysstat_gpa
  3489                              <1> 	;jc	short sysstat_err1
  3490                              <1> sysstat6:
  3491                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2
  3492 000040DE 81FE[24690000]      <1> 	cmp	esi, inode + 64 ; Retro UNIX v2 inode		
  3493                              <1> 	;cmp	esi, inode + 32
  3494                              <1> 		; cmp r2,$inode+32 / done?
  3495 000040E4 75E9                <1> 	jne	short sysstat5
  3496                              <1> 		; bne 1b / no, go back
  3497                              <1> 
  3498                              <1> 	;;;
  3499                              <1> 	; 09/05/2022
  3500                              <1> 	;*** additional feature *** -retro unix only- 
  3501                              <1> 	;
  3502                              <1> 	; !! return device number -of current inode- in eax !!
  3503                              <1> 	;
  3504                              <1> 	; (modification reason/purpose:
  3505                              <1> 	; to improve 'pwd' command's pathname output/result
  3506                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3507                              <1> 	; error due to same inode numbers in root file system
  3508                              <1> 	; and mounted file system.)
  3509                              <1> 	;
  3510 000040E6 29C0                <1> 	sub	eax, eax
  3511 000040E8 A0[406D0000]        <1> 	mov	al, [idev] ; [cdev]
  3512 000040ED A3[646D0000]        <1> 	mov	[u.r0], eax
  3513                              <1> 	;;;  
  3514                              <1> 
  3515 000040F2 E996F1FFFF          <1> 	jmp	sysret
  3516                              <1> 		; br sysret3 / return through sysret
  3517                              <1> 	;
  3518                              <1> sysstat_gpa: ; get physical address of file status buffer
  3519                              <1> 	; 02/09/2015
  3520 000040F7 8B1D[886D0000]      <1> 	mov 	ebx, [u.base]
  3521                              <1> 	; 07/10/2015
  3522 000040FD E8CEE7FFFF          <1> 	call	get_physical_addr ; get physical address
  3523                              <1> 	;jc	short sysstat_gpa1
  3524 00004102 7294                <1> 	jc	short sysstat_err1
  3525                              <1> 	; 18/10/2015
  3526 00004104 89C7                <1> 	mov	edi, eax ; physical address
  3527                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3528                              <1> ;sysstat_gpa1:
  3529 00004106 C3                  <1> 	retn
  3530                              <1> 
  3531                              <1> fclose:
  3532                              <1> 	; 12/03/2022
  3533                              <1> 	; 11/02/2022
  3534                              <1> 	; 08/01/2022
  3535                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3536                              <1> 	; 08/04/2021
  3537                              <1> 	; 04/04/2021
  3538                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3539                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3540                              <1> 	;            (32 bit offset pointer modification)
  3541                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3542                              <1> 	;
  3543                              <1> 	; Given the file descriptor (index to the u.fp list)
  3544                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3545                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3546                              <1> 	; u.fp list is cleared. If all the processes that opened
  3547                              <1> 	; that file close it, then fsp etry is freed and the file
  3548                              <1> 	; is closed. If not a return is taken. 
  3549                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3550                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3551                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3552                              <1> 	; a check is made to see if the file is special.	
  3553                              <1> 	;
  3554                              <1> 	; INPUTS ->
  3555                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3556                              <1> 	;    u.fp - list of entries in the fsp table
  3557                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3558                              <1> 	; OUTPUTS ->
  3559                              <1> 	;    r1 - contains the same file descriptor
  3560                              <1> 	;    r2 - contains i-number
  3561                              <1> 	;
  3562                              <1> 	; ((AX = R1))
  3563                              <1> 	; ((Modified registers: edx, ebx, ecx, esi, edi, ebp))
  3564                              <1> 	;
  3565                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3566                              <1> 	;              if i-number of the file is 0. (error)
  3567                              <1> 
  3568                              <1> 	; 08/04/2021
  3569                              <1> 	; INPUT:
  3570                              <1> 	;	eax = file descriptor
  3571                              <1> 	; OUTPUT:
  3572                              <1> 	;	cf = 0 -> eax = file descriptor
  3573                              <1> 	;	cf = 1 -> file not open ; 11/02/2022
  3574                              <1> 
  3575                              <1> 	; 18/08/2020
  3576                              <1> 	;movzx	edx, ax ; **
  3577 00004107 89C3                <1> 	mov	ebx, eax
  3578                              <1> 
  3579                              <1> 	; 18/08/2020
  3580                              <1> _fclose:
  3581 00004109 53                  <1> 	push	ebx ; ***  ; file descriptor (index to u.fp)
  3582                              <1> 
  3583                              <1> 	;push	ax ; ***
  3584                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3585                              <1> 			     ; / the index to u.fp list)
  3586                              <1> 	; ebx = file descriptor/number
  3587 0000410A E840000000          <1> 	call	getf
  3588                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3589                              <1> 			    ; / cdev has device =, u.fofp 
  3590                              <1> 			    ; / points to 3rd word of fsp entry
  3591                              <1> 	;cmp	eax, 1 ; 18/08/2020
  3592 0000410F 6683F801            <1> 	cmp	ax, 1 ; r1
  3593                              <1> 		; tst r1 / is i-number 0?
  3594 00004113 7238                <1> 	jb	short fclose_2
  3595                              <1> 		; beq 1f / yes, i-node not active so return
  3596                              <1> 		; tst (r0)+ / no, jump over error return
  3597                              <1> 	
  3598                              <1> 	;mov	ebx, edx ; **
  3599                              <1>  	; 18/08/2020
  3600 00004115 8B1C24              <1> 	mov	ebx, [esp]
  3601                              <1> 	;mov	edx, eax 
  3602                              <1> 	;;mov 	dx, ax ; *
  3603                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3604                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3605                              <1> 			    ; / which is index to u.fp ; **
  3606 00004118 C683[6E6D0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3607                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3608 0000411F 8B1D[786D0000]      <1> 	mov	ebx, [u.fofp]
  3609                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3610                              <1> 
  3611                              <1> 	; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3612                              <1> 	; ebx = 5th word of fsp entry (64 bit file offset)
  3613                              <1> fclose_0:
  3614                              <1> 	; 08/01/2022
  3615 00004125 FE4BFE              <1> 	dec	byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2
  3616                              <1> 	;dec	byte [ebx+4] ; 18/06/2015
  3617                              <1> 		; decb 2(r1) / decrement the number of processes 
  3618                              <1> 			   ; / that have opened the file
  3619 00004128 7923                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3620                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3621                              <1> 	;
  3622                              <1> 	;push	dx ; *
  3623                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3624                              <1> 	;;xor	ax, ax ; 0
  3625                              <1> 	;xor	eax, eax ; 18/08/2020
  3626                              <1> 		; clear 1st word of fsp entry
  3627                              <1> 	;mov	[ebx-8], ax ; 0 ; 18/08/2020
  3628                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3629 0000412A 66C743F80000        <1> 	mov	word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number
  3630                              <1> 			; Note: 32 bit i-node number field is ready but
  3631                              <1> 			;	it is not used in current runix version.	
  3632                              <1> 
  3633                              <1> 	;;mov	[ebx-4], ax ; 0
  3634                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3635                              <1> 	;mov	al, [ebx+5] ; 18/06/2015
  3636                              <1> 	;	; tstb	3(r1) / has this file been deleted
  3637                              <1> 	;and	al, al
  3638                              <1> 	;jz	short fclose_1
  3639                              <1> 	;	; beq 2f / no, branch
  3640                              <1> 
  3641                              <1> 	;push	edx ; * ; 18/08/2020
  3642                              <1> 	;mov	eax, edx ; * ; 18/08/2020
  3643                              <1> 
  3644                              <1> 	;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3645                              <1> 	;;test	byte [ebx-3], 80h ; open mode & status flags
  3646                              <1> 	; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure)
  3647                              <1> 	;test	byte [ebx-4], 80h ; open mode & status flags 
  3648                              <1> 	;jz	short fclose_1	; deleted file flag (bit 7)
  3649                              <1> 
  3650                              <1> 	; 04/04/2021
  3651 00004130 31D2                <1> 	xor	edx, edx
  3652                              <1> 	; 08/01/2022
  3653 00004132 8A53FD              <1> 	mov	dl, [ebx-3] ; open mode & status flags
  3654 00004135 F6C280              <1> 	test	dl, 80h	    ; deleted file flag (bit 7)
  3655 00004138 7409                <1> 	jz	short fclose_1 ; (not deleted -while open-)
  3656 0000413A 52                  <1> 	push	edx
  3657                              <1> 	; 12/03/2022
  3658 0000413B 50                  <1> 	push	eax ; inode number 
  3659                              <1> 
  3660                              <1> 	; deleted file !
  3661                              <1> 
  3662                              <1> 	;mov	ax, dx ; *
  3663                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3664                              <1> 	; AX = inode number
  3665 0000413C E850050000          <1> 	call	anyi
  3666                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3667                              <1> 			    ; / check if file appears in fsp again
  3668                              <1> 	; 12/03/2022
  3669 00004141 58                  <1> 	pop	eax ; inode number
  3670                              <1> 	; 04/04/2021
  3671 00004142 5A                  <1> 	pop	edx
  3672                              <1> 	; 11/02/2022
  3673                              <1> 	;(cpu will come here if anyi returns -without error-)
  3674                              <1> 	;; 08/04/2021
  3675                              <1> 	;jc	short fclose_3 ; error code in eax	
  3676                              <1> 	;; 18/08/2020
  3677                              <1> 	;;jmp	short fclose_2
  3678                              <1> 
  3679                              <1> 	; ax = inode number
  3680                              <1> fclose_1: ; 2:
  3681                              <1> 	; 04/04/2021
  3682 00004143 80E201              <1> 	and	dl, 1
  3683 00004146 FEC2                <1> 	inc	dl ; 0 -> 1 (open for read), 1 -> 2 (open for write)
  3684                              <1> 	
  3685                              <1> 	;pop	eax ; * ; 18/08/2020 
  3686                              <1> 	;;pop	ax ; *
  3687                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3688 00004148 E811170000          <1> 	call	iclose ; close if it is special file 
  3689                              <1> 		; jsr r0,iclose / check to see if it is a special file
  3690                              <1> 	; 11/02/2022
  3691                              <1> 	;(cpu will come here if iclose returns -without error-)
  3692                              <1> 	;; 08/04/2021
  3693                              <1> 	;jnc	short fclose_2
  3694                              <1> ;fclose_3:
  3695                              <1> ;	pop	ebx ; ***  ; file descriptor
  3696                              <1> ;	; eax = error code
  3697                              <1> ;	retn
  3698                              <1> fclose_2: ; 1:
  3699 0000414D 58                  <1> 	pop	eax ; *** ; 18/08/2020
  3700                              <1> 	;pop	ax ; ***
  3701                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3702 0000414E C3                  <1> 	retn
  3703                              <1> 		; rts r0
  3704                              <1> 
  3705                              <1> 	; 08/01/2022
  3706                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3707                              <1> getf:	; / get the device number and the i-number of an open file
  3708                              <1> 	; 13/05/2015
  3709                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3710                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3711                              <1> 
  3712                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3713                              <1> 	;
  3714                              <1> 	; 16/05/2021
  3715                              <1> 	; 27/03/2020 - Retro UNIX 386 v2 
  3716                              <1> 	;	(new open files -fsp- structure)
  3717                              <1> 	; 13/05/2015
  3718                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3719                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3720                              <1> 	
  3721                              <1> 	; INPUT: 
  3722                              <1> 	;    ;eax = file descriptor/number
  3723                              <1> 	;     ebx = file descriptor/number ; 18/08/2020 	
  3724                              <1> 	; OUTPUT:
  3725                              <1> 	;     bl = open mode & status flag ; 27/03/2020
  3726                              <1> 	;        (bit 0 open mode flag, 0 = read, 1 = write)  
  3727                              <1> 	;    eax = inode number (in AX)
  3728                              <1> 	;          If eax = 0 -> file not open
  3729                              <1> 	;   byte [cdev] = logical drive number (of inode in eax)
  3730                              <1> 	;	
  3731                              <1> 	; Modified registers: eax, ebx
  3732                              <1> 
  3733                              <1> 	; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c')
  3734                              <1> 	; /*
  3735                              <1> 	;  * Convert a user supplied
  3736                              <1> 	;  * file descriptor into a pointer
  3737                              <1> 	;  * to a file structure.
  3738                              <1> 	;  * Only task is to check range
  3739                              <1> 	;  * of the descriptor.
  3740                              <1> 	;  */
  3741                              <1> 	; struct file *
  3742                              <1> 	; getf(f)
  3743                              <1> 	;
  3744                              <1> 	; 18/08/2020
  3745                              <1> 	; 	ebx = file descriptor/number
  3746                              <1> 
  3747                              <1> 	; 16/05/2021
  3748                              <1> 	;NOFILE	equ 10 ; 08/01/2022
  3749                              <1> 
  3750                              <1> 	; 18/08/2020
  3751                              <1> 	;mov	ebx, eax
  3752                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3753                              <1> 
  3754                              <1> 	; ebx = file descriptor/number
  3755                              <1> 
  3756                              <1> 	; 18/08/2020
  3757 0000414F 29C0                <1> 	sub	eax, eax ; eax = 0
  3758                              <1>  
  3759 00004151 83FB0A              <1> 	cmp	ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021
  3760                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3761 00004154 732E                <1>         jnb	short getf2 ; 13/05/2015
  3762                              <1> 	;jnb	error
  3763                              <1> 		; bhis error3 / u.fp is table of users open files,
  3764                              <1> 			    ; / index in fsp table
  3765                              <1> 	; 08/01/2022
  3766 00004156 8A83[6E6D0000]      <1> 	mov	al, [ebx+u.fp]
  3767                              <1> 	;mov	bl, [ebx+u.fp]
  3768                              <1> 		; movb u.fp(r1),r1 / r1 contains number of entry 
  3769                              <1> 		                 ; / in fsp table
  3770 0000415C 08C0                <1> 	or	al, al ; 08/01/2022
  3771                              <1> 	;or	bl, bl
  3772                              <1> 	;jnz	short getf3
  3773 0000415E 7424                <1> 	jz	short getf2 ; 18/08/2020
  3774                              <1> 	;;jz	short getf4
  3775                              <1> 		; beq 1f / if its zero return
  3776                              <1> ;getf2:
  3777                              <1> ;	; 'File not open !' error (ax=0)
  3778                              <1> ;	;sub	eax, eax ; 18/08/2020
  3779                              <1> ;	retn
  3780                              <1> ;getf3:	
  3781                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3782                              <1> 	;
  3783                              <1> 	; 'fsp' table (10 bytes/entry)
  3784                              <1> 	; bit 15				   bit 0
  3785                              <1> 	; ---|-------------------------------------------
  3786                              <1> 	; r/w|		i-number of open file
  3787                              <1> 	; ---|-------------------------------------------
  3788                              <1> 	;		   device number
  3789                              <1> 	; -----------------------------------------------
  3790                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3791                              <1> 	; -----------------------------------------------
  3792                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3793                              <1> 	; ----------------------|------------------------
  3794                              <1> 	;  flag that says file 	| number of processes
  3795                              <1> 	;   has been deleted	| that have file open 
  3796                              <1> 	; ----------------------|------------------------
  3797                              <1> 
  3798                              <1> 	; Retro UNIX 386 v2 modification ! (27/03/2020)
  3799                              <1> 
  3800                              <1> 	; bit 15 				    bit 0
  3801                              <1> 	; ----------------------------------------------- byte 0
  3802                              <1> 	;    	       i-number of open file           
  3803                              <1> 	; ----------------------------------------------- byte 2
  3804                              <1> 	;          high word of 32 bit i-number       
  3805                              <1> 	; ----------------------------------------------- byte 4
  3806                              <1> 	;    open mode & status  |   device number     
  3807                              <1> 	; ----------------------------------------------- byte 6
  3808                              <1> 	;       reserved byte    |    open count  
  3809                              <1> 	; ----------------------------------------------- byte 8
  3810                              <1> 	;   offset pointer, i.e., r/w pointer to file 
  3811                              <1> 	; ----------------------------------------------- byte 10
  3812                              <1> 	;     64 bit file offset pointer (bit 16-31)  
  3813                              <1> 	; ----------------------------------------------- byte 12
  3814                              <1> 	;     64 bit file offset pointer (bit 32-47)   
  3815                              <1> 	; ----------------------------------------------- byte 14
  3816                              <1> 	;     64 bit file offset pointer (bit 48-63)  
  3817                              <1> 	; ----------------------------------------------- byte 16
  3818                              <1> 	
  3819                              <1> 	; 11/05/2015 - Retro UNIX 386 v1
  3820                              <1> 	;mov	eax, 10
  3821                              <1> 
  3822                              <1> 	; 27/03/2020 - Retro UNIX 386 v2	
  3823                              <1> 	;mov	eax, opfls.size ; mov eax, 16
  3824                              <1> 	
  3825                              <1> 	;sub	eax, eax ; 18/08/2020 ; eax = 0
  3826                              <1> 
  3827                              <1> 	;mov	al, opfls.size  ; mov al, 16
  3828                              <1> 	;
  3829                              <1> 	;mul	bl
  3830                              <1> 	;;mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3831                              <1> 	;; 27/03/2020
  3832                              <1> 	;mov	ebx, fsp-(opfls.size-opfls.offset) ; fsp-8
  3833                              <1> 	
  3834                              <1> 	;add	ebx, eax
  3835                              <1> 		; asl r1
  3836                              <1> 		; asl r1 / multiply by 8 to get index into 
  3837                              <1> 		       ; / fsp table entry
  3838                              <1> 		; asl r1
  3839                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3840                              <1> 			      ; / in the fsp entry
  3841                              <1> 	; 08/01/2022
  3842 00004160 88C3                <1> 	mov	bl, al
  3843                              <1> 	; 18/08/2020
  3844 00004162 FECB                <1> 	dec	bl ; zero based fsp table entry number
  3845                              <1> 	;shl	bl, 4 ; * 16 ; opfls.size
  3846                              <1> 	; 08/01/2022
  3847 00004164 C1E304              <1> 	shl	ebx, 4 ; * 16 ; opfls.size
  3848 00004167 81C3[DC690000]      <1> 	add	ebx, fsp+8 ; opfls.offset	
  3849                              <1> 	; ebx = address of the file offset pointer 
  3850                              <1> 	;	(not file offset! not fsp entry address !)
  3851                              <1> 
  3852 0000416D 891D[786D0000]      <1> 	mov	[u.fofp], ebx
  3853                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3854                              <1> 			     ; / in fsp entry in u.fofp
  3855                              <1> 	; 18/08/2020
  3856 00004173 8A43FD              <1> 	mov	al, [ebx-3]  ; open mode & status flags
  3857                              <1> 
  3858 00004176 50                  <1> 	push	eax
  3859                              <1> 
  3860                              <1> 	;mov	ax, [ebx]
  3861                              <1> 	;;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3862                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3863                              <1> 			     ;;dev number is in 1 byte
  3864                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3865                              <1> 
  3866                              <1> 	; 18/08/2020
  3867 00004177 8A43FC              <1> 	mov	al, [ebx-4]  ; logical drive number
  3868                              <1> 
  3869 0000417A A2[416D0000]        <1> 	mov	[cdev], al
  3870                              <1> 
  3871                              <1> 	;dec	ebx
  3872                              <1> 	;dec	ebx
  3873                              <1> 	; 18/08/2020
  3874 0000417F 668B43F8            <1> 	mov	ax, [ebx-8]
  3875                              <1> 		; mov -(r1),r1 / and the i-number r1
  3876                              <1> 
  3877 00004183 5B                  <1> 	pop	ebx ; ebx = bl = open mode and status flag
  3878                              <1> 		; (bit 0 is open mode flag, 0 = read, 1 = write)
  3879                              <1> 	; eax = inode number (in ax)	
  3880                              <1> 
  3881                              <1> getf2:	; 18/08/2020
  3882                              <1> getf4:	; 1: ; 08/01/2022
  3883 00004184 C3                  <1> 	retn
  3884                              <1> 		; rts r0
  3885                              <1> 
  3886                              <1> 	; 15/05/2022
  3887                              <1> 	; 08/01/2022
  3888                              <1> 	; 19/12/2021
  3889                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3890                              <1> namei:
  3891                              <1> 	; 18/10/2021
  3892                              <1> 	; 12/06/2021
  3893                              <1> 	; 01/05/2021
  3894                              <1> 	; 26/03/2021
  3895                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  3896                              <1> 	; 04/12/2015 (14 byte file names)
  3897                              <1> 	; 18/10/2015 (nbase, ncount)
  3898                              <1> 	; 12/10/2015
  3899                              <1> 	; 21/08/2015
  3900                              <1> 	; 18/07/2015
  3901                              <1> 	; 02/07/2015
  3902                              <1> 	; 17/06/2015
  3903                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3904                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3905                              <1> 	;
  3906                              <1> 	; 'namei' takes a file path name and returns i-number of
  3907                              <1> 	; the file in the current directory or the root directory
  3908                              <1> 	; (if the first character of the pathname is '/').	
  3909                              <1> 	;
  3910                              <1> 	; INPUTS ->
  3911                              <1> 	;    u.namep - points to a file path name
  3912                              <1> 	;    u.cdir - i-number of users directory
  3913                              <1> 	;    u.cdev - device number on which user directory resides	
  3914                              <1> 	; OUTPUTS ->
  3915                              <1> 	;    r1 - i-number of file
  3916                              <1> 	;    cdev
  3917                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3918                              <1> 	;               occurs in the search for file path name.
  3919                              <1> 	;	        If no match u.dirp points to the end of 
  3920                              <1> 	;               the directory and r1 = i-number of the current
  3921                              <1> 	;	        directory.	
  3922                              <1> 	; ((AX = R1))
  3923                              <1> 	;
  3924                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3925                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3926                              <1> 	;
  3927                              <1> 
  3928                              <1> 	;mov	ax, [u.cdir]
  3929                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3930                              <1> 			      ; / in r1
  3931                              <1> 	; 01/05/2021
  3932 00004185 A1[686D0000]        <1> 	mov	eax, [u.cdir]	
  3933 0000418A 8A15[6C6D0000]      <1> 	mov	dl, [u.cdrv]
  3934 00004190 8815[416D0000]      <1> 	mov	[cdev], dl
  3935                              <1> 	;mov	dx, [u.cdrv]
  3936                              <1> 	;mov	[cdev], dx	; NOTE: Retro UNIX 8086 v1 
  3937                              <1> 				; device/drive number is in 1 byte, 
  3938                              <1> 				; not in 1 word!
  3939                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3940                              <1> 				; / into cdev
  3941                              <1> 	; 12/10/2015
  3942                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3943                              <1>       	; convert virtual (pathname) addr to physical address
  3944 00004196 E849010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3945                              <1> 		; esi = physical address of [u.namep]
  3946                              <1> 		; ecx = byte count in the page
  3947 0000419B 803E2F              <1> 	cmp	byte [esi], '/'
  3948                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3949 0000419E 751C                <1> 	jne	short namei_1
  3950                              <1> 		; bne 1f
  3951 000041A0 FF05[806D0000]      <1> 	inc	dword [u.namep]
  3952                              <1> 		; inc u.namep / go to next char
  3953                              <1> 	;dec	cx ; remain byte count in the page
  3954 000041A6 49                  <1> 	dec	ecx ; 18/10/2021
  3955 000041A7 7506                <1> 	jnz	short namei_0
  3956                              <1> 	; 12/10/2015
  3957 000041A9 E836010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3958                              <1> 		; esi = physical address (page start + offset)
  3959                              <1> 		; ecx = byte count in the page
  3960 000041AE 4E                  <1> 	dec	esi
  3961                              <1> namei_0:
  3962 000041AF 46                  <1> 	inc 	esi  ; go to next char
  3963                              <1> 	;mov	ax, [rootdir] ; 09/07/2013
  3964                              <1> 	; 18/10/2021
  3965 000041B0 A1[466D0000]        <1> 	mov	eax, [rootdir]
  3966                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3967 000041B5 C605[416D0000]00    <1> 	mov	byte [cdev], 0
  3968                              <1> 		; clr cdev / clear device number
  3969                              <1> namei_1: ; 1:
  3970 000041BC F606FF              <1> 	test	byte [esi], 0FFh
  3971                              <1> 	;jz	short getf4
  3972                              <1> 	; 26/03/2021
  3973                              <1> 	;jz	short getf2 ; retn
  3974                              <1> 	;;jz	nig
  3975                              <1> 		; tstb *u.namep / is the character in file name a nul
  3976                              <1> 		; beq nig / yes, end of file name reached; 
  3977                              <1> 			; / branch to "nig"
  3978                              <1> 	; 19/12/2021
  3979                              <1> namei_9:
  3980                              <1> 	; 12/06/2021
  3981                              <1> 	;jnz	short namei_2
  3982                              <1> 	;retn
  3983                              <1> 	; 08/01/2022
  3984 000041BF 74C3                <1> 	jz	short getf4
  3985                              <1> namei_2: ; 1:
  3986                              <1> 	; 18/10/2015
  3987 000041C1 8935[E86D0000]      <1> 	mov 	[nbase], esi
  3988                              <1> 	;mov 	[ncount], cx
  3989                              <1> 	; 18/10/2021
  3990 000041C7 890D[EC6D0000]      <1> 	mov	[ncount], ecx
  3991                              <1> 	;
  3992                              <1> 	;;mov	dx, 2
  3993                              <1> 	;mov	dl, 2 ; user flag (read, non-owner)
  3994                              <1> 	; 25/03/2021
  3995                              <1> 	;mov	dx, 100h ; IREAD - read, owner 
  3996                              <1> 	; 18/10/2021
  3997 000041CD 29D2                <1> 	sub	edx, edx
  3998 000041CF FEC6                <1> 	inc	dh ; dx = 100h ; IREAD - read, owner 
  3999 000041D1 E8990B0000          <1> 	call	access
  4000                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  4001                              <1> 	; 'access' will not return here if user has not "r" permission !
  4002                              <1> 
  4003                              <1> 	;test 	word [i.flgs], 4000h
  4004                              <1> 	;	; bit $40000,i.flgs / directory i-node?
  4005                              <1>         ;jz	short namei_err
  4006                              <1> 		; beq error3 / no, got an error
  4007                              <1> 	; 26/03/2021 
  4008                              <1> ;	mov	al, [i.flgs+1]
  4009                              <1> ;	;test	al, 80h ; IFREG ; 80h
  4010                              <1> ;	;jz	short namei_err ; not a regular file ! (device!?)
  4011                              <1> ;	;and	al, 40h ; IFDIR ; 40h
  4012                              <1> ;	;jz	short namei_err ; not a sub directory !
  4013                              <1> ;	shl	al, 1 ; 80h (IFREG flag) -> cf = 1
  4014                              <1> ;	jnc	short namei_err ; not a regular file ! (device!?)
  4015                              <1> ;	shl	al, 1 ; 80h (IFDIR flag) -> cf = 1
  4016                              <1> ;	jnc	short namei_err ; not a sub directory !
  4017                              <1> 
  4018                              <1> 	; 27/03/2021
  4019 000041D6 E83A010000          <1> 	call	chk_dir ; check for directory, jump to 'error' if not
  4020                              <1> 	; CPU will be here if the inode is a (valid) directory inode
  4021                              <1> 
  4022                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  4023                              <1> 	;xor	eax, eax
  4024                              <1> 	;mov	[u.off], eax ; 0
  4025                              <1> 	; 01/05/2021 - Retro UNIX 386 v2 inode structure
  4026 000041DB A1[EC680000]        <1> 	mov	eax, [i.size]
  4027                              <1> 	;mov	ax, [i.size]
  4028 000041E0 A3[7C6D0000]        <1> 	mov	[u.dirp], eax
  4029                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  4030                              <1> 		; clr u.off / u.off is file offset used by user
  4031                              <1> 	; 18/10/2021
  4032 000041E5 31C0                <1> 	xor	eax, eax
  4033                              <1> 	;mov	[u.off], eax ; 0
  4034 000041E7 BB[846D0000]        <1> 	mov	ebx, u.off
  4035 000041EC 8903                <1> 	mov	[ebx], eax ; mov dword [u.off], 0
  4036                              <1> 	;
  4037 000041EE 891D[786D0000]      <1> 	mov	[u.fofp], ebx ; u.off ; 18/10/2021
  4038                              <1> 	;mov	dword [u.fofp], u.off
  4039                              <1> 			; mov $u.off,u.fofp / u.fofp is a pointer to 
  4040                              <1> 				  ; / the offset portion of fsp entry
  4041                              <1> namei_3: ; 2:
  4042 000041F4 C705[886D0000]-     <1> 	mov	dword [u.base], u.dirbuf
  4042 000041FA [9C6D0000]          <1>
  4043                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  4044                              <1> 				    ; / copied from a directory
  4045 000041FE C705[8C6D0000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  4045 00004206 0000                <1>
  4046                              <1>  		; mov $10.,u.count / u.count is byte count 
  4047                              <1> 				 ; / for reads and writes
  4048                              <1> 	;mov 	ax, [ii]
  4049                              <1> 	; 18/10/2021
  4050 00004208 A1[3C6D0000]        <1> 	mov	eax, [ii] ; (32 bit inode number)
  4051                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  4052 0000420D FE05[D66D0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  4053 00004213 E8D90D0000          <1>     	call	readi
  4054                              <1> 		; jsr r0,readi / read 10. bytes of file 
  4055                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  4056                              <1> 
  4057 00004218 8B0D[906D0000]      <1> 	mov 	ecx, [u.nread]
  4058 0000421E 09C9                <1> 	or 	ecx, ecx
  4059                              <1> 		; tst u.nread
  4060 00004220 741A                <1> 	jz	short nib
  4061                              <1> 		; ble nib / gives error return
  4062                              <1> 	;
  4063                              <1> 	;mov 	bx, [u.dirbuf]
  4064                              <1> 	;and 	bx, bx       
  4065                              <1> 	; 18/10/2021
  4066 00004222 66F705[9C6D0000]FF- <1> 	test	word [u.dirbuf], 0FFFFh
  4066 0000422A FF                  <1>
  4067                              <1> 		; tst u.dirbuf /
  4068 0000422B 7513                <1> 	jnz	short namei_4
  4069                              <1> 		; bne 3f / branch when active directory entry 
  4070                              <1> 		       ; / (i-node word in entry non zero)
  4071 0000422D A1[846D0000]        <1> 	mov	eax, [u.off]
  4072 00004232 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  4073 00004235 A3[7C6D0000]        <1> 	mov	[u.dirp], eax
  4074                              <1> 		; mov u.off,u.dirp
  4075                              <1> 		; sub $10.,u.dirp
  4076 0000423A EBB8                <1> 	jmp	short namei_3
  4077                              <1> 		; br 2b
  4078                              <1> 
  4079                              <1> 	; 18/07/2013
  4080                              <1> nib: 
  4081 0000423C 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  4082 0000423E F9                  <1> 	stc
  4083                              <1> nig:
  4084 0000423F C3                  <1> 	retn
  4085                              <1> 
  4086                              <1> 	; 27/03/2021
  4087                              <1> ;namei_err:
  4088                              <1> 	; 16/06/2015
  4089                              <1> ;	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  4090                              <1> ;	jmp	error
  4091                              <1> 
  4092                              <1> namei_4: ; 3:
  4093                              <1> 	; 18/10/2015
  4094                              <1> 	; 12/10/2015
  4095                              <1> 	; 21/08/2015
  4096                              <1> 	; 18/07/2015
  4097 00004240 8B2D[806D0000]      <1> 	mov	ebp, [u.namep]
  4098                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  4099 00004246 BF[9E6D0000]        <1> 	mov 	edi, u.dirbuf + 2
  4100                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  4101                              <1> 	; 18/10/2015
  4102 0000424B 8B35[E86D0000]      <1> 	mov	esi, [nbase]
  4103                              <1> 	;mov	cx, [ncount]
  4104                              <1> 	;and	cx, cx
  4105                              <1> 	; 18/10/2021
  4106 00004251 8B0D[EC6D0000]      <1> 	mov	ecx, [ncount]
  4107 00004257 21C9                <1> 	and	ecx, ecx
  4108 00004259 7505                <1> 	jnz	short namei_5	
  4109                              <1> 	;
  4110 0000425B E88A000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4111                              <1> 		; esi = physical address (page start + offset)
  4112                              <1> 		; ecx = byte count in the page
  4113                              <1> namei_5: ; 3:
  4114 00004260 45                  <1> 	inc	ebp ; 18/07/2015
  4115 00004261 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  4116                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  4117 00004262 08C0                <1> 	or 	al, al
  4118 00004264 741C                <1> 	jz 	short namei_7
  4119                              <1> 		; beq 3f / if char is nul, then the last char in string
  4120                              <1> 			; / has been moved
  4121 00004266 3C2F                <1> 	cmp	al, '/'
  4122                              <1> 		; cmp r4,$'/ / is char a </>
  4123 00004268 7418                <1> 	je 	short namei_7
  4124                              <1> 		; beq 3f	
  4125                              <1> 	; 12/10/2015
  4126                              <1> 	;dec	cx ; remain byte count in the page
  4127 0000426A 49                  <1> 	dec	ecx ; 18/10/2021
  4128 0000426B 7505                <1> 	jnz	short namei_6
  4129 0000426D E878000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4130                              <1> 		; esi = physical address (page start + offset)
  4131                              <1> 		; ecx = byte count in the page
  4132                              <1> namei_6:
  4133 00004272 81FF[AC6D0000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4134                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  4135                              <1> 				     ; / all 8 bytes of file name
  4136 00004278 74E6                <1> 	je	short namei_5
  4137                              <1> 		; beq 3b
  4138 0000427A AE                  <1> 	scasb	
  4139                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  4140                              <1> 			      ; / char read from directory
  4141 0000427B 74E3                <1> 	je 	short namei_5
  4142                              <1> 		; beq 3b / branch if chars match
  4143                              <1> namei_10:
  4144 0000427D E972FFFFFF          <1>         jmp	namei_3 ; 2b
  4145                              <1> 		; br 2b / file names do not match go to next directory entry
  4146                              <1> namei_7: ; 3:
  4147 00004282 81FF[AC6D0000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4148                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  4149 00004288 7405                <1> 	je	short namei_8
  4150                              <1> 		; beq 3f
  4151                              <1> 	;mov 	ah, [edi]
  4152                              <1> 	;;inc 	edi 
  4153                              <1> 	;and 	ah, ah
  4154                              <1> 	;	; tstb (r3)+ /
  4155                              <1>         ; 18/10/2021
  4156 0000428A F607FF              <1> 	test	byte [edi], 0FFh
  4157                              <1> 	; 08/01/2021
  4158 0000428D 75EE                <1> 	jnz	short namei_10 
  4159                              <1> 	;jnz	namei_3
  4160                              <1> 		; bne 2b
  4161                              <1> namei_8: ; 3
  4162 0000428F 892D[806D0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  4163                              <1> 		; mov r2,u.namep / u.namep points to char 
  4164                              <1> 			       ; / following a / or nul
  4165                              <1> 	;mov	bx, [u.dirbuf]
  4166                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  4167                              <1> 				; / entry to r1
  4168                              <1> 
  4169                              <1> 	;;;;
  4170                              <1> 	; 15/05/2022 - Retro UNIX (8086/386) feature only !
  4171                              <1> 	; ! 'pwd' utility modification !
  4172                              <1> 	; ((if directory entry name is a dotdot)))
  4173                              <1> 	;; check if it is mounted device's root directory inode
  4174                              <1> 	; and if so, replace it with parent dir inode number
  4175                              <1> 	;  of mounting directory in [mntp].
  4176                              <1> 
  4177 00004295 0FB71D[9C6D0000]    <1> 	movzx	ebx, word [u.dirbuf]
  4178                              <1> 
  4179 0000429C 6683FB01            <1> 	cmp	bx, 1 ; root directory inode number
  4180 000042A0 7539                <1> 	jne	short namei_11
  4181                              <1> 
  4182 000042A2 3B1D[3C6D0000]      <1> 	cmp	ebx, [ii] ; for root dir, '.' & '..' is 1
  4183 000042A8 7531                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  4184                              <1> 
  4185                              <1> 	;cmp	[idev], bh ; 0
  4186 000042AA 383D[416D0000]      <1> 	cmp	[cdev], bh ; 0
  4187                              <1> 			; 0 = root fs, dev num in [rdev]
  4188                              <1> 			; 1 = mounted, dev num in [mdev]
  4189 000042B0 7629                <1> 	jna	short namei_11
  4190                              <1> 
  4191                              <1> 	; dotdot (parent directory link) check
  4192 000042B2 66813D[9E6D0000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  4192 000042BA 2E                  <1>
  4193 000042BB 751E                <1> 	jne	short namei_11
  4194 000042BD 803D[A06D0000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  4195 000042C4 7515                <1> 	jne	short namei_11
  4196                              <1> 	
  4197                              <1> 	; (This may not be necessary because [idev] = 1
  4198                              <1> 	; and [mnti] is expected as a sub dir inode number)
  4199 000042C6 391D[4A6D0000]      <1> 	cmp	[mnti], ebx ; 1
  4200 000042CC 760D                <1> 	jna	short namei_11
  4201                              <1> 	
  4202                              <1> 	; change inumber to parent dir inum of mount directory
  4203 000042CE 8B1D[4E6D0000]      <1> 	mov	ebx, [mntp]
  4204 000042D4 C605[416D0000]00    <1> 	mov	byte [cdev], 0 ; root fs
  4205                              <1> namei_11:
  4206                              <1> 	;;;;
  4207                              <1> 
  4208 000042DB 20C0                <1> 	and 	al, al
  4209                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  4210                              <1> 		      ;  / if r4 = </> then go to next directory
  4211                              <1> 	; 15/05/2022
  4212 000042DD 89D8                <1> 	mov	eax, ebx
  4213                              <1> 	;;mov	ax, bx
  4214                              <1> 	;;mov 	ax, [u.dirbuf] ; 17/06/2015
  4215                              <1>         ;; 18/10/2021 (16 bit inode number in 32 bit register)
  4216                              <1> 	;movzx	eax, word [u.dirbuf] 
  4217                              <1> 	; 19/12/2021
  4218 000042DF E9DBFEFFFF          <1> 	jmp	namei_9 ; eax = inode number
  4219                              <1> ;	jnz	namei_2 
  4220                              <1> ;		; bne 1b
  4221                              <1> ;	; AX = i-number of the file
  4222                              <1> ;;;nig:
  4223                              <1> ;	retn
  4224                              <1> 		; tst (r0)+ / gives non-error return
  4225                              <1> ;;nib:
  4226                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  4227                              <1> 		       ; ax = 0 -> file not found 
  4228                              <1> ;;	stc	; 27/05/2013
  4229                              <1> ;;	retn
  4230                              <1> 		; rts r0
  4231                              <1> 
  4232                              <1> trans_addr_nmbp:
  4233                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4234                              <1> 	; 18/10/2015
  4235                              <1> 	; 12/10/2015
  4236 000042E4 8B2D[806D0000]      <1> 	mov 	ebp, [u.namep]
  4237                              <1> trans_addr_nm: 
  4238                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4239                              <1> 	; Convert virtual (pathname) address to physical address
  4240                              <1> 	; (Retro UNIX 386 v1 feature only !)
  4241                              <1> 	; 18/10/2015
  4242                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  4243                              <1> 	; 02/07/2015
  4244                              <1> 	; 17/06/2015
  4245                              <1> 	; 16/06/2015
  4246                              <1> 	;
  4247                              <1> 	; INPUTS: 
  4248                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  4249                              <1> 	;	[u.pgdir] = user's page directory
  4250                              <1> 	; OUTPUT:
  4251                              <1> 	;       esi = physical address of the pathname
  4252                              <1> 	;	ecx = remain byte count in the page
  4253                              <1> 	;
  4254                              <1> 	; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021
  4255                              <1> 	;
  4256                              <1> 
  4257                              <1> 	; 18/10/2021
  4258 000042EA 29C9                <1> 	sub	ecx, ecx
  4259                              <1> 	;
  4260                              <1>         ;cmp	dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  4261 000042EC 390D[C86D0000]      <1> 	cmp	[u.ppgdir], ecx ; 0 ; 18/10/2021
  4262 000042F2 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  4263                              <1> 				     ; it is already physical address
  4264 000042F4 50                  <1>    	push	eax	
  4265 000042F5 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  4266 000042F7 E8D4E5FFFF          <1>        	call	get_physical_addr ; get physical address
  4267 000042FC 7204                <1> 	jc	short tr_addr_nm_err
  4268                              <1> 	; 18/10/2015
  4269                              <1> 	; eax = physical address 
  4270                              <1> 	; ecx = remain byte count in page (1-4096) ; 18/10/2021
  4271                              <1> 		; 12/10/2015 (cx = [u.pncount])
  4272 000042FE 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  4273 00004300 58                  <1> 	pop	eax 
  4274 00004301 C3                  <1> 	retn
  4275                              <1> 
  4276                              <1> tr_addr_nm_err:
  4277 00004302 A3[D86D0000]        <1> 	mov	[u.error], eax
  4278                              <1> 	;pop 	eax
  4279 00004307 E961EFFFFF          <1> 	jmp	error
  4280                              <1> 
  4281                              <1> trans_addr_nmk:
  4282                              <1> 	; 12/10/2015
  4283                              <1> 	; 02/07/2015
  4284 0000430C 8B35[806D0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  4285                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  4286                              <1> 	; 18/10/2021
  4287 00004312 B510                <1> 	mov	ch, PAGE_SIZE/256
  4288 00004314 C3                  <1> 	retn
  4289                              <1> 
  4290                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  4291                              <1> chk_dir:
  4292                              <1> 	; 12/06/2021
  4293                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  4294                              <1> 	; Check for directory inode
  4295                              <1> 
  4296 00004315 8A0D[E5680000]      <1> 	mov	cl, [i.flgs+1]
  4297                              <1> 	;test	cl, 80h ; IFREG ; 80h
  4298                              <1> 	;jz	short chk_dir_err ; not a regular file ! (device!?)
  4299                              <1> 	;and	cl, 40h ; IFDIR ; 40h
  4300                              <1> 	;jz	short chk_dir_err ; not a sub directory !
  4301 0000431B D0E1                <1> 	shl	cl, 1 ; 80h (IFREG flag) -> cf = 1
  4302 0000431D 7305                <1> 	jnc	short chk_dir_err ; not a regular file ! (device!?)
  4303 0000431F D0E1                <1> 	shl	cl, 1 ; 40h (IFDIR flag) -> cf = 1
  4304 00004321 7301                <1> 	jnc	short chk_dir_err ; not a sub directory !
  4305                              <1> 	; 12/06/2021
  4306 00004323 C3                  <1> 	retn
  4307                              <1> chk_dir_err:
  4308 00004324 C705[D86D0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4308 0000432C 0000                <1>
  4309 0000432E E93AEFFFFF          <1> 	jmp	error
  4310                              <1> 
  4311                              <1> 	; 06/02/2022
  4312                              <1> 	; 08/01/2022
  4313                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  4314                              <1> syschdir:
  4315                              <1> 	; / makes the directory specified in the argument
  4316                              <1> 	; / the current directory
  4317                              <1> 	;
  4318                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  4319                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4320                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  4321                              <1> 	;
  4322                              <1> 	; 'syschdir' makes the directory specified in its argument
  4323                              <1> 	; the current working directory.
  4324                              <1> 	;
  4325                              <1> 	; Calling sequence:
  4326                              <1> 	;	syschdir; name
  4327                              <1> 	; Arguments:
  4328                              <1> 	;	name - address of the path name of a directory
  4329                              <1> 	;	       terminated by nul byte.	
  4330                              <1> 	; Inputs: -
  4331                              <1> 	; Outputs: -
  4332                              <1> 	; ...............................................................
  4333                              <1> 	;				
  4334                              <1> 	; Retro UNIX 8086 v1 modification:
  4335                              <1> 	;	 The user/application program puts address of 
  4336                              <1> 	;	 the path name in BX register as 'syschdir' 
  4337                              <1> 	; 	 system call argument.
  4338                              <1> 
  4339 00004333 891D[806D0000]      <1> 	mov	[u.namep], ebx
  4340                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  4341 00004339 E847FEFFFF          <1> 	call	namei
  4342                              <1> 		; jsr r0,namei / find its i-number
  4343                              <1> 	;jc	error
  4344                              <1> 		; br error3
  4345 0000433E 730F                <1> 	jnc	short syschdir0
  4346                              <1> 	; 'directory not found !' error
  4347 00004340 C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  4347 00004348 0000                <1>
  4348 0000434A E91EEFFFFF          <1> 	jmp	error
  4349                              <1> syschdir0:
  4350                              <1> 	; 08/01/2022
  4351 0000434F 66BA0001            <1> 	mov	dx, 100h  ; read access ; IREAD (100h)
  4352 00004353 E8170A0000          <1> 	call	access
  4353                              <1> 		; jsr r0,access; 2 / get i-node into core
  4354                              <1> 	
  4355                              <1> 	; 06/02/2022
  4356                              <1> 	;; 01/01/2022 (runix v2 fs inode flag)
  4357                              <1> 	;test	byte [i.flgs+1], 80h ; regular file ?
  4358                              <1> 	;jz	short syschdir2 ; no, error!
  4359                              <1> 	;test	byte [i.flgs+1], 40h ; directory flag ?
  4360                              <1> 	;;test	word [i.flgs], 4000h
  4361                              <1> 	;	; bit $40000,i.flgs / is it a directory?
  4362                              <1> 	;;jz	error 
  4363                              <1> 	;	; beq error3 / no error
  4364                              <1> 	;jnz	short syschdir1
  4365                              <1> ;syschdir2:
  4366                              <1> 	;mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4367                              <1> 	;jmp	error
  4368                              <1> 
  4369                              <1> 	; 06/02/2022
  4370                              <1> 	; check for directory, jump to 'error' if not
  4371 00004358 E8B8FFFFFF          <1> 	call	chk_dir
  4372                              <1> 	; (cpu will not return here
  4373                              <1> 	;  if the inode it is not a valid dir inode)
  4374                              <1> 
  4375                              <1> syschdir1:
  4376 0000435D 66A3[686D0000]      <1> 	mov	[u.cdir], ax
  4377                              <1> 		; mov r1,u.cdir / move i-number to users 
  4378                              <1> 			      ; / current directory
  4379                              <1> 	;mov	ax, [cdev]
  4380                              <1> 	;mov	[u.cdrv], ax
  4381                              <1> 	; 08/01/2022
  4382 00004363 A0[416D0000]        <1> 	mov	al, [cdev]
  4383 00004368 A2[6C6D0000]        <1> 	mov	[u.cdrv], al
  4384                              <1> 		; mov cdev,u.cdev / move its device to users 
  4385                              <1> 			        ; / current device
  4386 0000436D E91BEFFFFF          <1> 	jmp	sysret
  4387                              <1> 		; br sysret3
  4388                              <1> 
  4389                              <1> syschmod: ; < change mode of file >
  4390                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4391                              <1> 	; 01/05/2021
  4392                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4393                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4394                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4395                              <1> 	;
  4396                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4397                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4398                              <1> 	; changed to 'mode'.
  4399                              <1> 	;
  4400                              <1> 	; Calling sequence:
  4401                              <1> 	;	syschmod; name; mode
  4402                              <1> 	; Arguments:
  4403                              <1> 	;	name - address of the file name
  4404                              <1> 	;	       terminated by null byte.
  4405                              <1> 	;	mode - (new) mode/flags < attributes >
  4406                              <1> 	;	
  4407                              <1> 	; Inputs: -
  4408                              <1> 	; Outputs: -
  4409                              <1> 	; ...............................................................
  4410                              <1> 	;				
  4411                              <1> 	; Retro UNIX 8086 v1 modification: 
  4412                              <1> 	;       'syschmod' system call has two arguments; so,
  4413                              <1> 	;	* 1st argument, name is pointed to by BX register
  4414                              <1> 	;	* 2nd argument, mode is in CX register
  4415                              <1> 	;
  4416                              <1> 	; Mode bits (Flags):
  4417                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4418                              <1> 	;	bit 14 - directory flag (4000h)
  4419                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4420                              <1> 	;	bit 12 - large file flag (1000h)
  4421                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4422                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4423                              <1> 	;	bit 4 - executable flag (10h)
  4424                              <1> 	;	bit 3 - read permission for owner (08h)
  4425                              <1> 	;	bit 2 - write permission for owner (04h)
  4426                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4427                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4428                              <1> 
  4429                              <1> 	; 01/05/2021 (07/02/2020)
  4430                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  4431                              <1> 	; 	bit 15 - IFREG - regular file (8000h)
  4432                              <1> 	;	bit 14 - IFDIR - directory (4000h)
  4433                              <1> 	;	bit 13 - IRSVD - 0 - reserved/mounted bit (2000h)
  4434                              <1> 	; 	bit 12 - ILARG - large file addressing bit (1000h)
  4435                              <1> 	; 	bit 11 - ISUID - set user id on exec (800h)
  4436                              <1> 	;	bit 10 - ISGID - set group id on exec (400h)
  4437                              <1> 	; 	bit  9 - IEXTT - 0 - use extents (200h)
  4438                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4439                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4440                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4441                              <1> 	; 	bit  5 - read, group (20h)
  4442                              <1> 	; 	bit  4 - write, group (10h)
  4443                              <1> 	; 	bit  3 - execute, group (08h)
  4444                              <1> 	;	bit  2 - read, others (04h)
  4445                              <1> 	; 	bit  1 - write, others (02h)
  4446                              <1> 	; 	bit  0 - execute, others (01h)
  4447                              <1> 	;
  4448                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  4449                              <1> 	;	bit 15 - IFREG - 0 - device file (8000h)
  4450                              <1> 	; 	bit 14 - IFBLK - block device (4000h)
  4451                              <1> 	; 	bit 13 - IFCHR - 1 - character special (2000h)
  4452                              <1> 	;	bit 12 - IFIFO - fifo special (1000h)
  4453                              <1> 	; 	bit 11 - IPIPE - pipe special (800h)
  4454                              <1> 	;	bit 10 - IREDIR - redirected (400h)
  4455                              <1> 	;	bit  9 - IEXTR - external device driver (200h)
  4456                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4457                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4458                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4459                              <1> 	; 	bit  5 - read, group (20h)
  4460                              <1> 	; 	bit  4 - write, group (10h)
  4461                              <1> 	; 	bit  3 - execute, group (08h)
  4462                              <1> 	;	bit  2 - read, others (04h)
  4463                              <1> 	; 	bit  1 - write, others (02h)
  4464                              <1> 	; 	bit  0 - execute, others (01h)
  4465                              <1> 
  4466                              <1> 	; / name; mode
  4467 00004372 E877000000          <1> 	call	isown
  4468                              <1> 		; jsr r0,isown / get the i-node and check user status
  4469                              <1> 
  4470                              <1> 	; 25/05/2020
  4471                              <1> 	; AL = new mode (return form 'isown', ecx -> eax)
  4472                              <1> 
  4473                              <1> 	;test	word [i.flgs], 4000h
  4474                              <1> 	;	; bit $40000,i.flgs / directory?
  4475                              <1> 	;jz	short syschmod1
  4476                              <1> 	;	; beq 2f / no
  4477                              <1> 	;; AL = (new) mode
  4478                              <1> 	;and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4479                              <1> 	;	; bic $60,r2 / su & ex / yes, clear set user id and 
  4480                              <1> 	;		   ; / executable modes
  4481                              <1> 
  4482                              <1> 	; 01/05/2021
  4483                              <1> 	; AX = new mode (9 bits for devices or 12 bits files)
  4484 00004377 8A15[E5680000]      <1> 	mov	dl, [i.flgs+1]
  4485                              <1> 	; 09/01/2022
  4486 0000437D F6C280              <1> 	test	dl, 80h ; regular file
  4487 00004380 7416                <1> 	jz	short syschmod1 ; device file
  4488 00004382 F6C240              <1> 	test	dl, 40h ; directory
  4489 00004385 7511                <1> 	jnz	short syschmod1
  4490                              <1> 	; regular file
  4491 00004387 6625FF0D            <1> 	and	ax, 0DFFh ; clear bit 9, 12-15 (of new mode)
  4492                              <1> 	; clear bit 8,10,11 of current mode/flags
  4493 0000438B 80E2F2              <1> 	and	dl, 0F2h ; and dl, 11110010b
  4494                              <1> syschmod0:
  4495 0000438E 08D4                <1> 	or	ah, dl
  4496 00004390 66A3[E4680000]      <1> 	mov	[i.flgs], ax	
  4497 00004396 EB45                <1> 	jmp	short syschmod2
  4498                              <1> syschmod1: 
  4499                              <1> 	; device or directory	
  4500 00004398 6625B601            <1> 	and	ax, 1B6h ; clear bit 9-15 & bit 0,3,6 (EXEC bits)
  4501                              <1> 	; clear bit 8 (IREAD) of current mode/flags
  4502                              <1> 	;	 (dl contains flag bits 8-15)
  4503 0000439C 80E2FE              <1> 	and	dl, ~1 ; and dl, 11111110b 
  4504 0000439F EBED                <1> 	jmp	short syschmod0
  4505                              <1> 
  4506                              <1> ;syschmod1: ; 2:
  4507                              <1> 	;mov	[i.flgs], al	
  4508                              <1> 	;	; movb r2,i.flgs / move remaining mode to i.flgs
  4509                              <1> 
  4510                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4511                              <1> 	;mov	byte [imodx], 1 ; (flag means file data is same
  4512                              <1> 	;			;  but inode's itself has been modified)
  4513                              <1> 	;call	setimod
  4514                              <1> 	;jmp	sysret
  4515                              <1> 
  4516                              <1> 	; 25/05/2020
  4517                              <1> 	;jmp	short syschmod2
  4518                              <1> 
  4519                              <1> syschown: ; < change owner of file >
  4520                              <1> 	; 13/03/2022
  4521                              <1> 	; 11/03/2022
  4522                              <1> 	; 14/02/2022
  4523                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4524                              <1> 	; 01/05/2021
  4525                              <1> 	;	(change owner and group ID of file)
  4526                              <1> 	; 02/04/2021
  4527                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4528                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4529                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4530                              <1> 	;
  4531                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4532                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4533                              <1> 	; changed to 'owner'
  4534                              <1> 	;
  4535                              <1> 	; Calling sequence:
  4536                              <1> 	;	syschown; name; owner
  4537                              <1> 	; Arguments:
  4538                              <1> 	;	name - address of the file name
  4539                              <1> 	;	       terminated by null byte.
  4540                              <1> 	;	owner - (new) owner (number/ID)
  4541                              <1> 	;	
  4542                              <1> 	; Inputs: -
  4543                              <1> 	; Outputs: -
  4544                              <1> 	; ...............................................................
  4545                              <1> 	;				
  4546                              <1> 	; Retro UNIX 8086 v1 modification: 
  4547                              <1> 	;       'syschown' system call has two arguments; so,
  4548                              <1> 	;	* 1st argument, name is pointed to by BX register
  4549                              <1> 	;	* 2nd argument, owner number is in CX register
  4550                              <1> 	;
  4551                              <1> 	; / name; owner
  4552 000043A1 E848000000          <1> 	call	isown
  4553                              <1> 		; jsr r0,isown / get the i-node and check user status
  4554                              <1> 	
  4555                              <1> 	; 25/05/2020
  4556                              <1> 	; AL = owner number (return form 'isown', ecx -> eax)
  4557                              <1> 	; 02/04/2021
  4558                              <1> 	; AX = owner number
  4559                              <1> 	; 01/05/2021
  4560                              <1> 	; byte 2 of EAX is group number
  4561                              <1> 
  4562                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013 
  4563                              <1> 	;	; tstb u.uid / super user
  4564                              <1> 	;jz	short syschown1
  4565                              <1> 	;	; beq 2f / yes, 2f
  4566 000043A6 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0
  4567 000043AE 741F                <1> 	jz	short syschown1
  4568                              <1> 
  4569                              <1> 	;test	byte [i.flgs], 20h ; 32
  4570                              <1> 	;	; bit $40,i.flgs / no, set userid on execution?
  4571                              <1> 	;;jnz	error
  4572                              <1> 	;	; bne 3f / yes error, could create Trojan Horses
  4573                              <1> 	;jz	short syschown1
  4574                              <1> 	; 01/05/2021
  4575                              <1> 	; check set user id on execution flag
  4576                              <1> 	; (protection against Trojan Horses)
  4577                              <1> 
  4578                              <1> 	; ((Note: UNIX v7 x86 'chown' source code in 'sys4.c'
  4579                              <1> 	;        does not contain this protection)) 
  4580                              <1> 
  4581                              <1> 	; 14/02/2022
  4582 000043B0 8A15[E5680000]      <1> 	mov	dl, [i.flgs+1]
  4583 000043B6 F6C280              <1> 	test	dl, 80h ; IFREG ; RUNIX v2 inode flags  	
  4584 000043B9 7405                <1> 	jz	short syschown_err ; device file !
  4585                              <1> 	; 09/01/2022
  4586                              <1> 	;test	byte [i.flgs+1], 08h ; ISUID ; RUNIX v2 inode flags  	
  4587                              <1> 	; 14/02/2022
  4588 000043BB F6C208              <1> 	test	dl, 08h	; set user id on execution
  4589 000043BE 740F                <1> 	jz	short syschown1 ; 11/03/2022
  4590                              <1> 		; 11/03/2022
  4591                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4592                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4593                              <1> syschown_err:
  4594                              <1> 	; 'permission denied !'
  4595 000043C0 C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4595 000043C8 0000                <1>
  4596 000043CA E99EEEFFFF          <1> 	jmp	error
  4597                              <1> syschown1: ; 2:
  4598                              <1> 	;; AL = owner (number/ID)
  4599                              <1> 	;mov	[i.uid], al ; 23/06/2015
  4600                              <1> 	;	; movb r2,i.uid / no, put the new owners id 
  4601                              <1> 	;		      ; / in the i-node
  4602                              <1> 	; 02/04/2021 (Retro UNIX 386 v2)
  4603                              <1> 	; AX = owner number
  4604 000043CF 66A3[E8680000]      <1> 	mov	[i.uid], ax ; owner
  4605                              <1> 	; 13/03/2022
  4606                              <1> 	;; 14/02/2022 (Retro UNIX 386 v1.2)
  4607                              <1> 	;test	dl, 04h ; ISGID ; set grup id on execution
  4608                              <1> 	;jz	short syschown2
  4609                              <1> 	; 01/05/2021 (Retro UNIX 386 v2)
  4610 000043D5 C1E810              <1> 	shr	eax, 16
  4611 000043D8 A2[EA680000]        <1> 	mov	[i.gid], al ; group
  4612                              <1> syschown2:
  4613                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4614                              <1> syschmod2:
  4615                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4616 000043DD C605[556D0000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  4617                              <1> 			      ;  but inode's itself has been modified)
  4618 000043E4 E82D0A0000          <1> 	call	setimod ; 25/05/2020
  4619                              <1> 	
  4620 000043E9 E99FEEFFFF          <1> 	jmp	sysret
  4621                              <1> 
  4622                              <1> 	; 1: 
  4623                              <1> 		; jmp sysret4
  4624                              <1> 	; 3:
  4625                              <1> 		; jmp	error
  4626                              <1> 
  4627                              <1> isown:
  4628                              <1> 	; 11/03/2022
  4629                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4630                              <1> 	; 06/11/2021
  4631                              <1> 	; 12/06/2021
  4632                              <1> 	; 01/05/2021
  4633                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4634                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4635                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4636                              <1> 	;
  4637                              <1> 	; 'isown' is given a file name (the 1st argument).
  4638                              <1> 	;  It find the i-number of that file via 'namei' 
  4639                              <1> 	;  then gets the i-node into core via 'iget'.
  4640                              <1> 	;  It then tests to see if the user is super user. 
  4641                              <1> 	;  If not, it checks to see if the user is owner of 
  4642                              <1> 	;  the file. If he is not an error occurs.
  4643                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4644                              <1> 	;  the inode has been modified and the 2nd argument of
  4645                              <1> 	;  the call is put in r2.
  4646                              <1> 	;
  4647                              <1> 	; INPUTS ->
  4648                              <1> 	;    arguments of syschmod and syschown calls
  4649                              <1> 	; OUTPUTS ->
  4650                              <1> 	;    u.uid - id of user
  4651                              <1> 	;    imod - set to a 1
  4652                              <1> 	;    r2 - contains second argument of the system call
  4653                              <1> 	;
  4654                              <1> 	;   ((AX=R2) output as 2nd argument)
  4655                              <1> 	;
  4656                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))
  4657                              <1> 	;
  4658                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4659                              <1> 	;; ! 2nd argument on top of stack !
  4660                              <1> 	;; 22/06/2015 - 32 bit modifications
  4661                              <1> 	;; 07/07/2013
  4662 000043EE 891D[806D0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4663 000043F4 51                  <1> 	push 	ecx ;* ; 2nd argument
  4664                              <1> 	;;
  4665 000043F5 E88BFDFFFF          <1> 	call	namei
  4666                              <1> 		; jsr r0,namei / get its i-number
  4667                              <1>        ; Retro UNIX 8086 v1 modification !
  4668                              <1>        ; ax = 0 -> file not found 
  4669                              <1> 	;and	ax, ax
  4670                              <1> 	;jz	error
  4671                              <1> 	;jc	error ; 27/05/2013
  4672                              <1> 		; br error3
  4673 000043FA 730F                <1> 	jnc	short isown1  ; 25/05/2020 (isown0 -> isown1)
  4674                              <1> 	; 'file not found !' error
  4675 000043FC C705[D86D0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4675 00004404 0000                <1>
  4676 00004406 E962EEFFFF          <1> 	jmp	error
  4677                              <1> isown1:
  4678 0000440B E875080000          <1> 	call	iget
  4679                              <1> 		; jsr r0,iget / get i-node into core
  4680                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  4681                              <1> 	;; 06/11/2021
  4682                              <1> 	;jnc	short isown3
  4683                              <1> 	;mov	[u.error], eax
  4684                              <1> 	;jmp	error
  4685                              <1> ;isown3:
  4686                              <1> 	; check if it is super user ID
  4687                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4688 00004410 66A1[B66D0000]      <1> 	mov	ax, [u.uid]
  4689 00004416 6609C0              <1> 	or	ax, ax
  4690                              <1> 	;mov	al, [u.uid] ; 02/08/2013
  4691                              <1> 	;or	al, al
  4692                              <1> 		; tstb u.uid / super user?
  4693                              <1> 	; 12/06/2021
  4694 00004419 7418                <1> 	jz	short isown2 ; 25/05/2020 (isown1 -> isown2)
  4695                              <1> 		; beq 1f / yes, branch
  4696                              <1> 	
  4697                              <1> 	; check user ID	(if same with file's owner)
  4698 0000441B 663B05[E8680000]    <1> 	cmp	ax, [i.uid] ; 09/01/2022
  4699                              <1> 	;cmp	al, [i.uid]
  4700                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4701                              <1> 				 ; / the file
  4702                              <1> 	;jne	error
  4703                              <1> 		; beq 1f / yes
  4704                              <1> 		; jmp error3 / no, error
  4705                              <1> 	; 11/03/2022
  4706 00004422 740F                <1> 	je	short isown2 ; 25/05/2020
  4707                              <1> 	;; 01/05/2021
  4708                              <1> 	;jne	short isown_err
  4709                              <1> 
  4710                              <1> 	; 11/03/2022 (*)
  4711                              <1> 	; Note: It is seen as original unix (v5-v7) kernel
  4712                              <1> 	;	source handles 'u.gid' for group permissions
  4713                              <1> 	;	but kernel uses 'u.uid' as primary and unic
  4714                              <1> 	;	(singular) user id/number; a user group
  4715                              <1> 	;	does/can not contain same user id/number
  4716                              <1> 	;	with anotner group. So, if active/current
  4717                              <1> 	;	user ID is same with file's owner id,
  4718                              <1> 	;	group id check is not needed.
  4719                              <1> 	;	([u.uid] = [i.uid] is enough to confirm)	
  4720                              <1> 
  4721                              <1> 	; 01/05/2021
  4722                              <1> 	;mov	ax, [u.uid]
  4723                              <1> 	;or	ax, ax
  4724                              <1> 	;jz	short isown2 
  4725                              <1> 	;cmp	ax, [i.uid]
  4726                              <1> 	;;je	short isown2
  4727                              <1> 	;jne	short isown_err
  4728                              <1> 
  4729                              <1> 	; 01/05/2021
  4730                              <1> 	; ((Note: UNIX v7 x86 'chown', 'chmod' procedures
  4731                              <1> 	;    and their sub procedures do not check group ID))
  4732                              <1> 	; (('sys4.c', 'fio.c'))
  4733                              <1> 
  4734                              <1> 	; 11/03/2022 (*)
  4735                              <1> 	; 01/05/2021
  4736                              <1> 	; check group ID (if same with group of file's owner)
  4737                              <1> 	;mov	al, [u.gid]
  4738                              <1> 	;cmp	al, [i.gid]
  4739                              <1> 	;je	short isown2
  4740                              <1> isown_err:
  4741 00004424 C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER ; 11
  4741 0000442C 0000                <1>
  4742                              <1> 			; 'permission denied !' error
  4743 0000442E E93AEEFFFF          <1> 	jmp	error
  4744                              <1> 
  4745                              <1> 	; 25/05/2020
  4746                              <1> ;isown2: ; 1:
  4747                              <1> ;	call	setimod
  4748                              <1> ;		; jsr r0,setimod / indicates 
  4749                              <1> ;		;	       ; / i-node has been modified
  4750                              <1> isown2: 
  4751                              <1> 	; 25/05/2020
  4752 00004433 58                  <1> 	pop	eax ;* ; 2nd argument
  4753                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4754                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4755 00004434 C3                  <1> 	retn
  4756                              <1> 
  4757                              <1> ;;arg:  ; < get system call arguments >
  4758                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4759                              <1> 	; of form:
  4760                              <1> 	;	sys 'routine' ; arg1
  4761                              <1> 	;		or
  4762                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4763                              <1> 	;		or
  4764                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4765                              <1> 	;	
  4766                              <1> 	; INPUTS ->
  4767                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4768                              <1> 	;	This pointers's value is actually the value of
  4769                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4770                              <1> 	;	made to process the sys instruction
  4771                              <1> 	;    r0 - contains the return address for the routine
  4772                              <1> 	;	that called arg. The data in the word pointer 
  4773                              <1> 	;	to by the return address is used as address
  4774                              <1> 	;	in which the extracted argument is stored
  4775                              <1> 	;    	
  4776                              <1> 	; OUTPUTS ->
  4777                              <1> 	;    'address' - contains the extracted argument 
  4778                              <1> 	;    u.sp+18 - is incremented by 2 
  4779                              <1> 	;    r1 - contains the extracted argument
  4780                              <1> 	;    r0 - points to the next instruction to be
  4781                              <1> 	;	 executed in the calling routine.
  4782                              <1> 	;
  4783                              <1>   
  4784                              <1> 	; mov u.sp,r1
  4785                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4786                              <1> 			; / into argument of arg2
  4787                              <1> 	; add $2,18.(r1) / point pc on stack 
  4788                              <1> 			      ; / to next system argument
  4789                              <1> 	; rts r0
  4790                              <1> 
  4791                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4792                              <1> 	; 'arg2' takes first argument in system call
  4793                              <1> 	;  (pointer to name of the file) and puts it in location
  4794                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4795                              <1> 	;  and on top of the stack
  4796                              <1> 	;	
  4797                              <1> 	; INPUTS ->
  4798                              <1> 	;    u.sp, r0
  4799                              <1> 	;    	
  4800                              <1> 	; OUTPUTS ->
  4801                              <1> 	;    u.namep
  4802                              <1> 	;    u.off 
  4803                              <1> 	;    u.off pushed on stack
  4804                              <1> 	;    r1
  4805                              <1> 	;
  4806                              <1> 
  4807                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4808                              <1> 				; / first arg in sys call
  4809                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4810                              <1> 				; / second arg in sys call
  4811                              <1> 	; mov r0,r1 / r0 points to calling routine
  4812                              <1> 	; mov (sp),r0 / put operation code back in r0
  4813                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4814                              <1> 			; / on stack
  4815                              <1> 	; jmp (r1) / return to calling routine
  4816                              <1> 
  4817                              <1> systime: ; / get time of year
  4818                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4819                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4820                              <1> 	;
  4821                              <1> 	; 20/06/2013
  4822                              <1> 	; 'systime' gets the time of the year.
  4823                              <1> 	; The present time is put on the stack.
  4824                              <1> 	;
  4825                              <1> 	; Calling sequence:
  4826                              <1> 	;	systime
  4827                              <1> 	; Arguments: -
  4828                              <1> 	;	
  4829                              <1> 	; Inputs: -
  4830                              <1> 	; Outputs: sp+2, sp+4 - present time
  4831                              <1> 	; ...............................................................
  4832                              <1> 	;	
  4833                              <1> 	; Retro UNIX 8086 v1 modification: 
  4834                              <1> 	;       'systime' system call will return to the user
  4835                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4836                              <1> 	;
  4837                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4838                              <1> 	;	system call for PC compatibility !!		 	
  4839                              <1> 
  4840 00004435 E809E9FFFF          <1> 	call 	epoch
  4841 0000443A A3[646D0000]        <1> 	mov 	[u.r0], eax
  4842                              <1> 		; mov s.time,4(sp)
  4843                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4844                              <1> 				   ; / on the stack
  4845                              <1> 		; br sysret4
  4846 0000443F E949EEFFFF          <1> 	jmp	sysret 
  4847                              <1> 
  4848                              <1> sysstime: ; / set time
  4849                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4850                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4851                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4852                              <1> 	;
  4853                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4854                              <1> 	;
  4855                              <1> 	; Calling sequence:
  4856                              <1> 	;	sysstime
  4857                              <1> 	; Arguments: -
  4858                              <1> 	;	
  4859                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4860                              <1> 	; Outputs: -
  4861                              <1> 	; ...............................................................
  4862                              <1> 	;	
  4863                              <1> 	; Retro UNIX 8086 v1 modification: 
  4864                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4865                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4866                              <1> 	; 
  4867                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4868                              <1> 	;	to get sysstime system call arguments from the user;
  4869                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4870                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4871                              <1> 	;
  4872                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4873                              <1> 	;	system call for PC compatibility !!	
  4874                              <1> 
  4875                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4876 00004444 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit user ID
  4877                              <1> 	;cmp	byte [u.uid], 0
  4878                              <1> 		; tstb u.uid / is user the super user
  4879                              <1> 	;ja	error
  4880                              <1> 		; bne error4 / no, error
  4881 0000444C 760F                <1> 	jna	short systime1
  4882                              <1> 	; 'permission denied !'
  4883 0000444E C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4883 00004456 0000                <1>
  4884 00004458 E910EEFFFF          <1> 	jmp	error
  4885                              <1> systime1:
  4886                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4887                              <1> 	; EBX = unix (epoch) time (from user)
  4888 0000445D 89D8                <1> 	mov	eax, ebx
  4889 0000445F E85FEAFFFF          <1> 	call 	set_date_time
  4890                              <1> 		; mov 4(sp),s.time
  4891                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4892 00004464 E924EEFFFF          <1> 	jmp	sysret
  4893                              <1> 		; br sysret4
  4894                              <1> 
  4895                              <1> sysbreak:
  4896                              <1> 	; 18/10/2015
  4897                              <1> 	; 07/10/2015
  4898                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4899                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4900                              <1> 	;
  4901                              <1> 	; 'sysbreak' sets the programs break points. 
  4902                              <1> 	; It checks the current break point (u.break) to see if it is
  4903                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4904                              <1> 	; even address (if it was odd) and the area between u.break
  4905                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4906                              <1> 	; in u.break and control is passed to 'sysret'.
  4907                              <1> 	;
  4908                              <1> 	; Calling sequence:
  4909                              <1> 	;	sysbreak; addr
  4910                              <1> 	; Arguments: -
  4911                              <1> 	;	
  4912                              <1> 	; Inputs: u.break - current breakpoint
  4913                              <1> 	; Outputs: u.break - new breakpoint 
  4914                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4915                              <1> 	; ...............................................................
  4916                              <1> 	;	
  4917                              <1> 	; Retro UNIX 8086 v1 modification:
  4918                              <1> 	;	The user/application program puts breakpoint address
  4919                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4920                              <1> 	; 	(argument transfer method 1)
  4921                              <1> 	;
  4922                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4923                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4924                              <1> 	;  NOTE:
  4925                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4926                              <1> 	;	'u.break' address) of user's memory for original unix's
  4927                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4928                              <1> 
  4929                              <1> 		; mov u.break,r1 / move users break point to r1
  4930                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4931                              <1> 		; blos 1f / yes, 1f
  4932                              <1> 	; 23/06/2015
  4933 00004469 8B2D[946D0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4934                              <1> 	;and	ebp, ebp
  4935                              <1> 	;jz	short sysbreak_3 
  4936                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4937                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4938 0000446F 8B15[5C6D0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4939 00004475 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4940                              <1> 	; 07/10/2015
  4941 00004478 891D[946D0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4942                              <1> 	;
  4943 0000447E 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4944                              <1> 			   ; with top of user's stack (virtual!)
  4945 00004480 7327                <1> 	jnb	short sysbreak_3
  4946                              <1> 		; cmp r1,sp / is it the same or higher 
  4947                              <1> 			  ; / than the stack?
  4948                              <1> 		; bhis 1f / yes, 1f
  4949 00004482 89DE                <1> 	mov	esi, ebx
  4950 00004484 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4951 00004486 7621                <1> 	jna	short sysbreak_3 
  4952                              <1> 	;push	ebx
  4953                              <1> sysbreak_1:
  4954 00004488 89EB                <1> 	mov	ebx, ebp  
  4955 0000448A E841E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4956 0000448F 0F826DFEFFFF        <1> 	jc	tr_addr_nm_err
  4957                              <1> 	; 18/10/2015
  4958 00004495 89C7                <1> 	mov	edi, eax 
  4959 00004497 29C0                <1> 	sub	eax, eax ; 0
  4960                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4961 00004499 39CE                <1> 	cmp	esi, ecx
  4962 0000449B 7302                <1> 	jnb	short sysbreak_2
  4963 0000449D 89F1                <1> 	mov	ecx, esi
  4964                              <1> sysbreak_2:
  4965 0000449F 29CE                <1> 	sub	esi, ecx
  4966 000044A1 01CD                <1> 	add	ebp, ecx
  4967 000044A3 F3AA                <1> 	rep 	stosb
  4968 000044A5 09F6                <1> 	or	esi, esi
  4969 000044A7 75DF                <1> 	jnz	short sysbreak_1
  4970                              <1> 	;
  4971                              <1> 		; bit $1,r1 / is it an odd address
  4972                              <1> 		; beq 2f / no, its even
  4973                              <1> 		; clrb (r1)+ / yes, make it even
  4974                              <1> 	; 2: / clear area between the break point and the stack
  4975                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4976                              <1> 		; bhis 1f / yes, quit
  4977                              <1> 		; clr (r1)+ / clear word
  4978                              <1> 		; br 2b / go back
  4979                              <1> 	;pop	ebx
  4980                              <1> sysbreak_3: ; 1:
  4981                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4982                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4983                              <1> 			; / in u.break (set new break point)
  4984                              <1> 		; br sysret4 / br sysret
  4985 000044A9 E9DFEDFFFF          <1> 	jmp	sysret
  4986                              <1> 
  4987                              <1> maknod: 
  4988                              <1> 	; 12/03/2022
  4989                              <1> 	; 11/03/2022
  4990                              <1> 	; 14/02/2022
  4991                              <1> 	; 10/01/2022
  4992                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4993                              <1> 	; 06/11/2021 (Retro UNIX 386 v2)
  4994                              <1> 	; 15/08/2021
  4995                              <1> 	; 06/05/2021
  4996                              <1> 	; 02/05/2021
  4997                              <1> 	; 01/04/2021
  4998                              <1> 	; 27/03/2021
  4999                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  5000                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5001                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  5002                              <1> 	;
  5003                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  5004                              <1> 	; for this i-node in the current directory.
  5005                              <1> 	;
  5006                              <1> 	; INPUTS ->
  5007                              <1> 	;    r1 - contains mode
  5008                              <1> 	;    ii - current directory's i-number	
  5009                              <1> 	;    	
  5010                              <1> 	; OUTPUTS ->
  5011                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  5012                              <1> 	;    i.flgs - flags in new i-node 
  5013                              <1> 	;    i.uid - filled with u.uid
  5014                              <1> 	;    i.nlks - 1 is put in the number of links
  5015                              <1> 	;    i.ctim - creation time
  5016                              <1> 	;    i.ctim+2 - modification time
  5017                              <1> 	;    imod - set via call to setimod
  5018                              <1> 	;	
  5019                              <1> 	; ((AX = R1)) input
  5020                              <1> 	;
  5021                              <1> 	; (Retro UNIX Prototype : 
  5022                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  5023                              <1>         ; ((Modified registers: eax, edx, ebx, ecx, esi, edi, ebp))
  5024                              <1> 
  5025                              <1> 	; 27/03/2021
  5026                              <1> 	; INPUT:
  5027                              <1>  	;	AX = mode
  5028                              <1> 	;
  5029                              <1> 	; ('maknod' is called by 'syscreat' and 'sysmkdir')
  5030                              <1> 	; (('syscreat' and 'sysmkdir' will set AX input))
  5031                              <1> 
  5032                              <1> 	; 27/03/2021
  5033                              <1> 	; Retro UNIX 386 v2 inode mode flags (ref: 'ux.s')
  5034                              <1> 	; for File Inode: (high byte)
  5035                              <1> 	;   IFREG - 1 = regular file (8000h)
  5036                              <1> 	;   IFDIR - 1 = directory (4000h)
  5037                              <1> 	;   IRSVD - 0 = reserved bit (2000h) ; Mounted flag for dirs
  5038                              <1> 	;   ILARG - large file addressing bit (1000h)
  5039                              <1> 	;   ISUID - set user id on exec (800h)
  5040                              <1> 	;   ISGID - set group id on exec (400h)
  5041                              <1> 	;   IEXTT - 1 = use extents (200h)
  5042                              <1> 	;   IREAD - read, owner (100h)
  5043                              <1> 	; for Device Inode: (high byte)
  5044                              <1> 	;   IFREG - 0 = device file (8000h)
  5045                              <1> 	;   IFBLK - 1 = block device (4000h)
  5046                              <1> 	;   IFCHR - character special (2000h) -always 1-
  5047                              <1> 	;   IFIFO - fifo special (1000h)
  5048                              <1> 	;   IPIPE - pipe special (800h) ; 07/02/2020
  5049                              <1> 	;   IREDIR - redirected (400h)  ; 07/02/2020
  5050                              <1> 	;   IEXTR - 1 = external device driver (200h)
  5051                              <1> 	;   IREAD - read, owner (100h)
  5052                              <1> 
  5053                              <1> 	;; / r1 contains the mode
  5054                              <1> 	;or 	ah, 80h	; 10000000b
  5055                              <1> 	;	; bis $100000,r1 / allocate flag set
  5056                              <1> 
  5057                              <1> 	; 14/02/2022
  5058                              <1> 	; input ->
  5059                              <1> 	;   [u.namep] points to the file name address
  5060                              <1> 	;	     (in the user's memory space)
  5061                              <1> 	;   [u.dirp] points to empty slot in the directory
  5062                              <1> 
  5063                              <1> 	; high 3 bit will be checked here
  5064                              <1> 	; 	(ref: unix v7 x86 source, iget.c)
  5065                              <1> 
  5066                              <1> ;	; 27/03/2021
  5067                              <1> ;	test	ah, 0E0h ; 80h+40h+20h
  5068                              <1> ;	jnz	short maknod0	
  5069                              <1> ;
  5070                              <1> ;	; ('syscreat' clears ILARG & IEXTT bits)
  5071                              <1> ;	;and	ah, ~0Ch ; clear ILARG & IEXTT bits
  5072                              <1> ;	;	; user can set ISUID & ISGID bits
  5073                              <1> ;
  5074                              <1> ;	or	ah, 80h ; IFREG
  5075                              <1> ;maknod0:
  5076 000044AE 50                  <1> 	push	eax ; ***** ; 27/03/2021 (32 bit push, pop)
  5077                              <1> 		; mov r1,-(sp) / put mode on stack
  5078                              <1> 	; 31/07/2013
  5079                              <1> 	;mov	ax, [ii] ; move current i-number to AX/r1
  5080                              <1> 	;	; mov ii,r1 / move current i-number to r1
  5081                              <1> 	;mov	dl, 1 ; owner flag mask
  5082                              <1> 	; 15/08/2021
  5083                              <1> 	;movzx	eax, word [ii] ; move current i-number to EAX
  5084                              <1> 	; 09/01/2022
  5085 000044AF A1[3C6D0000]        <1> 	mov	eax, [ii] ; move current i-number to EAX
  5086                              <1> 	; 25/03/2021
  5087 000044B4 66BA8000            <1> 	mov	dx, 80h	; IWRITE - write,owner
  5088 000044B8 E8B2080000          <1> 	call	access	
  5089                              <1> 		; jsr r0,access; 1 / get its i-node into core
  5090                              <1> 	; 15/08/2021
  5091                              <1> 	; NOTE: cpu will not return here if there is a permission error
  5092                              <1> 	;	(it will jump to 'error' address from/in 'access')
  5093                              <1> 	
  5094 000044BD 50                  <1> 	push	eax ; **** (parent) ; 27/03/2021 (32 bit push, pop)
  5095                              <1> 		; mov r1,-(sp) / put i-number on stack
  5096                              <1> 	;mov	ax, 40
  5097                              <1> 	;	; mov $40.,r1 / r1 = 40
  5098                              <1> 	; 27/03/2021
  5099 000044BE 31C0                <1> 	xor	eax, eax
  5100                              <1> 	;;dec	ax ; 0FFFFh
  5101                              <1> 	; 15/08/2021
  5102                              <1> 	;dec	eax ; 0FFFFFFFFh
  5103                              <1> 	; 01/04/2021
  5104                              <1> ;maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  5105                              <1> 	;;inc	ax
  5106                              <1> 	;	; inc r1 / r1 = r1 + 1
  5107                              <1> 	; 15/08/2021
  5108                              <1> 	;inc	eax
  5109                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5110                              <1> 	; eax = 0 -> start from first free inode
  5111                              <1> 	; eax > 0 -> locate this inode on the inode map buffer
  5112                              <1> 	; NOTE:
  5113                              <1> 	; Retro UNIX 386 v2 'imap' is mostly different than v1 'imap'
  5114                              <1> 	; ('imap' will not check inode table)
  5115 000044C0 E89F0A0000          <1> 	call	imap
  5116                              <1> 		; jsr r0,imap / get byte address and bit position in 
  5117                              <1> 			    ; /	inode map in r2 & m
  5118                              <1> 	; 09/01/2022
  5119                              <1> 	; (cpu will not return here if there would be an eror in imap)
  5120                              <1> 	; 15/08/2021
  5121                              <1> 	;jc	short maknod_err
  5122                              <1> 
  5123                              <1> 	; DX (MQ) has a 1 in the calculated bit position
  5124                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  5125                              <1> 
  5126                              <1> 	; 06/11/2021
  5127                              <1> 	; ebp = superblock buffer address
  5128                              <1> 	; eax = inode number
  5129                              <1> 	; 10/01/2022
  5130                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5131                              <1> 	;		of current IMAP sector	
  5132                              <1> 
  5133                              <1> 	; 27/03/2021
  5134                              <1> 	; If cpu is here, there is not an error
  5135                              <1> 	; and EBX points to inode map buffer
  5136                              <1> 	; DL has 1 at bit position which is for free inode
  5137                              <1> 	; (E)AX = inode number
  5138                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  5139                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5140                              <1> 
  5141                              <1> 	; 15/08/2021
  5142                              <1> maknod1:
  5143                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  5144                              <1> 	;	       Inode count must be checked here
  5145                              <1> 	; (Original UNIX v1 did not check inode count here !?)
  5146 000044C5 8413                <1> 	test	[ebx], dl
  5147                              <1> 		; bitb mq,(r2) / is the i-node active
  5148                              <1> 	;jnz	short maknod1
  5149                              <1> 	;	; bne 1b / yes, try the next one
  5150                              <1> 	; 15/08/2021
  5151 000044C7 7408                <1> 	jz	short maknod3 ; free inode (inactive inode)
  5152                              <1> maknod2:
  5153 000044C9 40                  <1> 	inc	eax
  5154 000044CA E8B90A0000          <1> 	call	imap_x ; next call to imap (bypass 1st call code)
  5155                              <1> 	; 10/01/2022
  5156                              <1> 	; (cpu will/would not return here 
  5157                              <1> 	;  if there is/was an error in 'imap_x')
  5158                              <1> 	;jnc	short maknod1
  5159 000044CF EBF4                <1> 	jmp	short maknod1
  5160                              <1> 
  5161                              <1> 	; 14/02/2022
  5162                              <1> ;maknod_err:
  5163                              <1> ;	; 15/08/2021
  5164                              <1> ;	;pop	edx  ; two pops for stack alignment
  5165                              <1> ;	;pop	edx  ; (may not be needed while jumping to 'error')
  5166                              <1> ;	mov	[u.error], eax
  5167                              <1> ;	jmp	error
  5168                              <1> maknod3:
  5169                              <1> 	; 10/01/2022
  5170                              <1> 	; ebp = superblock buffer address
  5171                              <1> 	; eax = (free) inode number
  5172                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5173                              <1> 	;			of current IMAP sector
  5174                              <1> 	; EBX = buffer address/offset for relevant alloc byte
  5175                              <1> 	;  DL has 1 at bit position which is for free inode
  5176                              <1> 	;
  5177                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5178                              <1> 
  5179                              <1> 	;mov	[ebp+SB.LastInode], eax ; (free) inode number
  5180                              <1> 
  5181 000044D1 50                  <1> 	push	eax ; ***
  5182 000044D2 51                  <1> 	push	ecx ; **
  5183 000044D3 52                  <1> 	push	edx ; *
  5184 000044D4 55                  <1> 	push	ebp ; @ ; 11/03/2022
  5185                              <1> 
  5186 000044D5 8B457C              <1> 	mov	eax, [ebp+SB.ImapBuffer]
  5187                              <1> 
  5188 000044D8 E815160000          <1> 	call	wslot
  5189                              <1> 	; ebx = buffer data address (write operation bit is set)
  5190                              <1> 	; eax = physical sector number
  5191                              <1> 	; Note: ebx contains addr of the 1st buffer in the buf chain
  5192                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  5193 000044DD 5D                  <1> 	pop	ebp ; @ ; 11/03/2022
  5194                              <1> 
  5195                              <1> 	;mov	[ebp+SB.ImapBuffer], ebx
  5196                              <1> 			; save inode map buffer address
  5197 000044DE 5A                  <1> 	pop	edx ; *
  5198 000044DF 59                  <1> 	pop	ecx ; **
  5199 000044E0 01CB                <1> 	add	ebx, ecx ; + byte offset (for allocation bit pos)	
  5200                              <1> 
  5201                              <1> 	; set allocation bit (for this new inode) ; 10/01/2022 
  5202 000044E2 0813                <1> 	or	[ebx], dl
  5203                              <1> 		; bisb mq,(r2) / no, make it active 
  5204                              <1> 			     ; / (put a 1 in the bit map)
  5205                              <1> 	;push	ebp ; @
  5206 000044E4 E816160000          <1> 	call	dskwr ; writes the 1st buffer to sector
  5207                              <1> 		      ; (at the beginning/head of the buffer chain)
  5208                              <1> 	;pop	ebp ; @
  5209                              <1> 
  5210                              <1> 	; if we are here, buffer has been written to disk successfully 
  5211                              <1> 	; (otherwise cpu would jump to 'error' address)
  5212                              <1> 
  5213                              <1> 	; set superblock modified flag
  5214 000044E9 BA[566D0000]        <1> 	mov	edx, smod
  5215 000044EE F605[416D0000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  5216 000044F5 7401                <1> 	jz	short maknod4 ; no, root device
  5217                              <1> 	; yes, mounted device
  5218                              <1> 	;mov	edx, mmod
  5219 000044F7 42                  <1> 	inc	edx ; edx = offset mmod
  5220                              <1> maknod4: 
  5221 000044F8 FE02                <1> 	inc	byte [edx] ; superblock modified !
  5222                              <1> 
  5223                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5224                              <1> 	;;
  5225                              <1> 	;; 27/03/2021
  5226                              <1> 	;; (ref: 'UNIXHDCP.ASM', 'mak_nod', 18/01/2020)
  5227                              <1> 	;or	byte [smod], 2 ; inode map modified
  5228                              <1> 	;; 01/04/2021
  5229                              <1> 	;;or	byte [imapbuf_hdr+bufhdr.status], 2
  5230                              <1> 	;or	byte [imapbuf_hdr], 2 ; set modified flag bit
  5231                              <1> 	; 02/05/2021
  5232                              <1> 	;or	byte [esi+ldrv.b_status], 2 ; inode map modified
  5233                              <1> 	; 15/08/2021
  5234                              <1> 	; 06/05/2021
  5235                              <1> 	;or	byte [esi+ldrv.status], 2 ; inode map modified
  5236                              <1> 	;;or	byte [sysbuf_hdr], 2 ; set modified flag bit
  5237                              <1> 	
  5238                              <1> 	;mov	eax, [ebp+SB.LastInode] ; (free) inode number
  5239                              <1> 	;push	eax ; ***
  5240                              <1> 
  5241                              <1> 	; 12/03/2022
  5242                              <1> 	; increase first free inode number
  5243 000044FA 8B0424              <1> 	mov	eax, [esp] ; ***
  5244 000044FD 40                  <1> 	inc	eax ; next inode number 
  5245                              <1> 		    ; (free inode search start value)
  5246 000044FE 894534              <1> 	mov	[ebp+SB.FirstFreeIno], eax
  5247                              <1> 
  5248                              <1> 	; 12/03/2022
  5249                              <1> 	; decrease free inode count
  5250 00004501 8B5530              <1> 	mov	edx, [ebp+SB.FreeInodes]
  5251                              <1> 	;cmp	edx, 0FFFFFFFFh
  5252                              <1> 	;je	short maknod5 ; invalid
  5253 00004504 42                  <1> 	inc	edx ; 0FFFFFFFFh -> 0
  5254 00004505 7405                <1> 	jz	short maknod5 ; invalid
  5255 00004507 4A                  <1> 	dec	edx
  5256 00004508 4A                  <1> 	dec	edx
  5257 00004509 895530              <1> 	mov	[ebp+SB.FreeInodes], edx ; -1
  5258                              <1> maknod5:
  5259 0000450C E844170000          <1> 	call	get_system_time
  5260                              <1> 		; eax = current time (as unix epoch time)
  5261 00004511 89455C              <1> 	mov	[ebp+SB.ModifTime], eax
  5262                              <1> 
  5263 00004514 58                  <1> 	pop	eax ; *** ; inode number
  5264                              <1> 	;;
  5265 00004515 E86B070000          <1> 	call	iget
  5266                              <1> 		; jsr r0,iget / get i-node into core
  5267                              <1> 	; 09/01/2022
  5268                              <1> 	;  (If cpu is here, there was/is not an error!)
  5269                              <1> 	; 06/11/2021
  5270                              <1> 	;jc	short maknod_err
  5271                              <1> 	
  5272                              <1> 	;test	word [i.flgs], 8000h 
  5273                              <1> 	;	; tst i.flgs / is i-node already allocated
  5274                              <1> 	;jnz	short maknod1	
  5275                              <1> 	;	; blt 1b / yes, look for another one
  5276                              <1> 	; 27/03/2021
  5277                              <1> 	; (Retro UNIX 386 v2 inode flags) 
  5278 0000451A F605[E5680000]E0    <1> 	test	byte [i.flgs+1], 0E0h ; 80h+40h+20h
  5279                              <1> 	;jnz	short maknod1 ; i-node already allocated
  5280                              <1> 	;		      ; (as it is in inode table)
  5281                              <1> 	; 15/08/2021
  5282 00004521 75A6                <1> 	jnz	short maknod2 ; defective inode map !?
  5283                              <1> 
  5284                              <1> 	; AX = free inode number
  5285 00004523 66A3[9C6D0000]      <1> 	mov	[u.dirbuf], ax
  5286                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  5287 00004529 58                  <1> 	pop	eax ; **** (parent) ; 27/03/2021 (32 bit push, pop)
  5288                              <1> 		; mov (sp)+,r1 / get current i-number back
  5289 0000452A E856070000          <1> 	call	iget
  5290                              <1> 		; jsr r0,iget / get i-node in core
  5291                              <1> 	; 09/01/2022
  5292                              <1> 	; 06/11/2021
  5293                              <1> 	;jc	short maknod_err
  5294                              <1> 
  5295                              <1> 	; 14/02/2022
  5296                              <1> 	; here..
  5297                              <1> 	;  [u.namep] points to the file name address
  5298                              <1> 	;	     (in the user's memory space)
  5299                              <1> 	;  [u.dirp] points to empty slot in the directory
  5300                              <1> 
  5301 0000452F E81AF7FFFF          <1> 	call	mkdir
  5302                              <1> 		; jsr r0,mkdir / make a directory entry 
  5303                              <1> 			     ; / in current directory
  5304                              <1> 	; 09/01/2022
  5305                              <1> 	;  (If cpu is here, there was/is not an error in 'mkdir'!)
  5306                              <1> 	; 06/11/2021
  5307                              <1> 	;jc	short maknod_err
  5308                              <1> 	
  5309                              <1> 	; (eax = 0)
  5310                              <1> 	;movzx	eax, [u.difbuf] ; 06/11/2021
  5311 00004534 66A1[9C6D0000]      <1> 	mov	ax, [u.dirbuf]
  5312                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  5313 0000453A E846070000          <1> 	call	iget
  5314                              <1> 		; jsr r0,iget / get it into core
  5315                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  5316                              <1> 	; 09/01/2022
  5317                              <1> 	; 06/11/2021
  5318                              <1> 	;jc	short maknod_err
  5319                              <1> 
  5320                              <1> 	;mov	ecx, 8
  5321                              <1> 	; 27/03/2021
  5322 0000453F 31C9                <1> 	xor	ecx, ecx 
  5323 00004541 B110                <1> 	mov	cl, 16 ; 64 bit inodes
  5324 00004543 31C0                <1> 	xor	eax, eax ; 0
  5325 00004545 BF[E4680000]        <1> 	mov	edi, inode 
  5326 0000454A F3AB                <1> 	rep	stosd
  5327                              <1> 	;
  5328                              <1> 	;pop	word [i.flgs]
  5329                              <1> 	;	; mov (sp)+,i.flgs / fill flags
  5330                              <1> 	; 27/03/2021 (32 bit push, pop)
  5331 0000454C 58                  <1> 	pop	eax ; *****
  5332 0000454D 66A3[E4680000]      <1> 	mov	[i.flgs], ax
  5333                              <1> 
  5334                              <1> 	;mov 	cl, [u.uid] ; 02/08/2013
  5335                              <1> 	;mov 	[i.uid], cl
  5336                              <1> 	;	; movb u.uid,i.uid / user id
  5337                              <1> 	; 15/08/2021
  5338                              <1> 	; 27/03/2021
  5339 00004553 8A0D[BA6D0000]      <1> 	mov	cl, [u.gid] ; 8 bit group ID ; 15/08/2021
  5340 00004559 880D[EA680000]      <1> 	mov	[i.gid], cl 	
  5341 0000455F 668B0D[B66D0000]    <1> 	mov	cx, [u.uid] ; 16 bit user ID
  5342 00004566 66890D[E8680000]    <1> 	mov	[i.uid], cx	
  5343                              <1> 
  5344 0000456D C605[E6680000]01    <1> 	mov     byte [i.nlks], 1
  5345                              <1> 		; movb $1,i.nlks / 1 link
  5346                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  5347                              <1> 	;mov	eax, [s.time]
  5348                              <1> 	;mov 	[i.ctim], eax
  5349                              <1> 	 	; mov s.time,i.ctim / time created
  5350                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  5351                              <1> 	; Retro UNIX 8086 v1 modification !
  5352                              <1> 	; i.ctime=0, i.ctime+2=0 and
  5353                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  5354                              <1> 	;call	setimod
  5355                              <1> 	;	; jsr r0,setimod / set modified flag
  5356                              <1> 	;retn
  5357                              <1> 	;	; rts r0 / return
  5358                              <1> 	; 27/03/2021
  5359 00004574 E99D080000          <1> 	jmp	setimod
  5360                              <1> 
  5361                              <1> sysseek: ; / moves read write pointer in an fsp entry
  5362                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5363                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5364                              <1> 	;
  5365                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  5366                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  5367                              <1> 	; The file descriptor refers to a file open for reading or
  5368                              <1> 	; writing. The read (or write) pointer is set as follows:
  5369                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  5370                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  5371                              <1> 	;	  current location plus offset.
  5372                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  5373                              <1> 	;	  size of file plus offset.
  5374                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  5375                              <1> 	;
  5376                              <1> 	; Calling sequence:
  5377                              <1> 	;	sysseek; offset; ptrname
  5378                              <1> 	; Arguments:
  5379                              <1> 	;	offset - number of bytes desired to move 
  5380                              <1> 	;		 the r/w pointer
  5381                              <1> 	;	ptrname - a switch indicated above
  5382                              <1> 	;
  5383                              <1> 	; Inputs: r0 - file descriptor 
  5384                              <1> 	; Outputs: -
  5385                              <1> 	; ...............................................................
  5386                              <1> 	;	
  5387                              <1> 	; Retro UNIX 8086 v1 modification: 
  5388                              <1> 	;       'sysseek' system call has three arguments; so,
  5389                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  5390                              <1> 	;	* 2nd argument, offset is in CX register
  5391                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  5392                              <1> 	;	
  5393                              <1> 
  5394 00004579 E820000000          <1> 	call	seektell
  5395                              <1> 	; AX = u.count
  5396                              <1> 	; BX = *u.fofp
  5397                              <1> 		; jsr r0,seektell / get proper value in u.count
  5398                              <1> 		; add u.base,u.count / add u.base to it
  5399 0000457E 0305[886D0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  5400 00004584 8903                <1> 	mov	[ebx], eax
  5401                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  5402 00004586 E902EDFFFF          <1> 	jmp	sysret
  5403                              <1> 		; br sysret4
  5404                              <1> 
  5405                              <1> systell: ; / get the r/w pointer
  5406                              <1> 	; 01/03/2022
  5407                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5408                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5409                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5410                              <1> 	;
  5411                              <1> 	; Retro UNIX 8086 v1 modification:
  5412                              <1> 	; ! 'systell' does not work in original UNIX v1,
  5413                              <1> 	; 	    it returns with error !
  5414                              <1> 	; Inputs: r0 - file descriptor 
  5415                              <1> 	; Outputs: r0 - file r/w pointer
  5416                              <1> 
  5417                              <1> 	;xor	ecx, ecx ; 0
  5418                              <1> 	;mov	edx, 1 ; 05/08/2013
  5419                              <1> 	; 09/01/2022
  5420 0000458B 29D2                <1> 	sub	edx, edx
  5421 0000458D FEC2                <1> 	inc	dl
  5422                              <1> 	; edx = 1
  5423                              <1> 	;call 	seektell
  5424 0000458F E810000000          <1> 	call 	seektell0 ; 05/08/2013
  5425                              <1> 	;mov	ebx, [u.fofp]
  5426                              <1> 	; 01/03/2022
  5427                              <1> 	;mov	eax, [ebx]
  5428 00004594 A3[646D0000]        <1> 	mov	[u.r0], eax
  5429 00004599 E9EFECFFFF          <1> 	jmp	sysret
  5430                              <1> 
  5431                              <1> ; Original unix v1 'systell' system call:
  5432                              <1> 		; jsr r0,seektell
  5433                              <1> 		; br error4
  5434                              <1> 
  5435                              <1> seektell:
  5436                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5437                              <1> 	; 06/11/2021
  5438                              <1> 	; 12/06/2021
  5439                              <1> 	; 06/05/2021 (Retro UNIX 386 v2)
  5440                              <1> 	; 03/01/2016
  5441                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5442                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5443                              <1> 	;
  5444                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  5445                              <1> 	; call in u.base and u.count. It then gets the i-number of
  5446                              <1> 	; the file from the file descriptor in u.r0 and by calling
  5447                              <1> 	; getf. The i-node is brought into core and then u.count
  5448                              <1> 	; is checked to see it is a 0, 1, or 2.
  5449                              <1> 	; If it is 0 - u.count stays the same
  5450                              <1> 	;          1 - u.count = offset (u.fofp)
  5451                              <1> 	;	   2 - u.count = i.size (size of file)
  5452                              <1> 	; 	 		
  5453                              <1> 	; !! Retro UNIX 8086 v1 modification:
  5454                              <1> 	;	Argument 1, file descriptor is in BX;
  5455                              <1> 	;	Argument 2, offset is in CX;
  5456                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  5457                              <1> 	;
  5458                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  5459                              <1> 	; call 	arg
  5460                              <1> 	;
  5461                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  5462                              <1> 	;
  5463 0000459E 890D[886D0000]      <1> 	mov 	[u.base], ecx ; offset
  5464                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  5465                              <1> 	; 09/01/2022
  5466                              <1> 	; ebx = file descriptor (0 to 9)
  5467                              <1> seektell0:
  5468 000045A4 8915[8C6D0000]      <1> 	mov 	[u.count], edx
  5469                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  5470                              <1> 	;mov	ax, bx
  5471                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  5472                              <1> 			     ; / (index in u.fp list)
  5473                              <1> 	; 12/06/2021
  5474                              <1> 	; BX = file descriptor (file number)
  5475 000045AA E8A0FBFFFF          <1> 	call	getf
  5476                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  5477                              <1> 	; 09/01/2022
  5478 000045AF 09C0                <1> 	or	eax, eax
  5479                              <1> 	;or	ax, ax ; i-number of the file
  5480                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  5481                              <1> 		             ; / put it on the stack
  5482                              <1> 	;jz	error
  5483                              <1> 		; beq error4 / if i-number is 0, not active so error
  5484 000045B1 750F                <1> 	jnz	short seektell1
  5485 000045B3 C705[D86D0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  5485 000045BB 0000                <1>
  5486 000045BD E9ABECFFFF          <1> 	jmp	error
  5487                              <1> seektell1:
  5488                              <1> 	; 06/05/2021
  5489                              <1> 	;push	eax
  5490                              <1> 	;cmp	ah, 80h
  5491                              <1> 	;jb	short seektell2
  5492                              <1> 	;	; bgt .+4 / if its positive jump
  5493                              <1> 	;neg	ax
  5494                              <1> 	;	; neg r1 / if not make it positive
  5495                              <1> seektell2:
  5496 000045C2 E8BE060000          <1> 	call	iget
  5497                              <1> 		; jsr r0,iget / get its i-node into core
  5498                              <1> 	; 09/01/2022
  5499                              <1> 	; (if there is/was an error in 'iget', cpu will not come here)
  5500                              <1> 	;; 06/11/2021
  5501                              <1> 	;jnc	short seektell6
  5502                              <1> 	;mov	[u.error], eax
  5503                              <1> 	;jmp	error
  5504                              <1> seektell6:
  5505 000045C7 8B1D[786D0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  5506 000045CD 803D[8C6D0000]01    <1> 	cmp	byte [u.count], 1
  5507                              <1> 		; cmp u.count,$1 / is ptr name =1
  5508 000045D4 7705                <1> 	ja	short seektell3
  5509                              <1> 		; blt 2f / no its zero
  5510 000045D6 7409                <1> 	je	short seektell4
  5511                              <1> 		; beq 1f / yes its 1
  5512 000045D8 31C0                <1> 	xor	eax, eax
  5513                              <1> 	;jmp	short seektell5
  5514 000045DA C3                  <1> 	retn
  5515                              <1> seektell3:
  5516                              <1> 	; 03/01/2016
  5517                              <1> 	;;movzx	eax, word [i.size]
  5518                              <1> 	;mov   	ax, [i.size]
  5519                              <1> 	;	; mov i.size,u.count /  put number of bytes 
  5520                              <1> 	;			; / in file in u.count
  5521                              <1> 	;;jmp	short seektell5
  5522                              <1> 	;	; br 2f
  5523                              <1> 	; 06/05/2021 - Retro UNIX 386 v2
  5524 000045DB A1[EC680000]        <1> 	mov	eax, [i.size]
  5525 000045E0 C3                  <1> 	retn
  5526                              <1> seektell4: ; 1: / ptrname =1
  5527                              <1> 	;mov	ebx, [u.fofp]
  5528 000045E1 8B03                <1> 	mov	eax, [ebx]
  5529                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  5530                              <1> ;seektell5: ; 2: / ptrname =0
  5531                              <1> 	;mov	[u.count], eax
  5532                              <1> 	;pop	eax 
  5533                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  5534 000045E3 C3                  <1> 	retn
  5535                              <1> 		; rts r0
  5536                              <1> 
  5537                              <1> sysintr: ; / set interrupt handling
  5538                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5539                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5540                              <1> 	;
  5541                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  5542                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  5543                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  5544                              <1> 	; If one does the interrupt character in the tty buffer is
  5545                              <1> 	; cleared and 'sysret'is called. If one does not exits
  5546                              <1> 	; 'sysret' is just called.	
  5547                              <1> 	;
  5548                              <1> 	; Calling sequence:
  5549                              <1> 	;	sysintr; arg
  5550                              <1> 	; Argument:
  5551                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  5552                              <1> 	;	    - if 1, intterupts cause their normal result
  5553                              <1> 	;		 i.e force an exit.
  5554                              <1> 	;	    - if arg is a location within the program,
  5555                              <1> 	;		control is passed to that location when
  5556                              <1> 	;		an interrupt occurs.	
  5557                              <1> 	; Inputs: -
  5558                              <1> 	; Outputs: -
  5559                              <1> 	; ...............................................................
  5560                              <1> 	;	
  5561                              <1> 	; Retro UNIX 8086 v1 modification: 
  5562                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  5563                              <1> 	;	then branches into sysquit.
  5564                              <1> 	;
  5565 000045E4 66891D[B06D0000]    <1> 	mov	[u.intr], bx
  5566                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  5567                              <1> 		; br 1f / go into quit routine
  5568 000045EB E99DECFFFF          <1> 	jmp	sysret
  5569                              <1> 
  5570                              <1> sysquit:
  5571                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5572                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5573                              <1> 	;
  5574                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  5575                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  5576                              <1> 	; tty exists. If one does the interrupt character in the tty
  5577                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  5578                              <1> 	; 'sysret' is just called.	
  5579                              <1> 	;
  5580                              <1> 	; Calling sequence:
  5581                              <1> 	;	sysquit; arg
  5582                              <1> 	; Argument:
  5583                              <1> 	;	arg - if 0, this call disables quit signals from the
  5584                              <1> 	;		typewriter (ASCII FS)
  5585                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  5586                              <1> 	;		cease and a core image to be produced.
  5587                              <1> 	;		 i.e force an exit.
  5588                              <1> 	;	    - if arg is an address in the program,
  5589                              <1> 	;		a quit causes control to sent to that
  5590                              <1> 	;		location.	
  5591                              <1> 	; Inputs: -
  5592                              <1> 	; Outputs: -
  5593                              <1> 	; ...............................................................
  5594                              <1> 	;	
  5595                              <1> 	; Retro UNIX 8086 v1 modification: 
  5596                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  5597                              <1> 	;	then branches into 'sysret'.
  5598                              <1> 	;
  5599 000045F0 66891D[B26D0000]    <1> 	mov	[u.quit], bx
  5600 000045F7 E991ECFFFF          <1> 	jmp	sysret
  5601                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  5602                              <1> 	;1:
  5603                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  5604                              <1> 			      ; / to r1
  5605                              <1> 		; beq sysret4 / return to user
  5606                              <1> 		; clrb 6(r1) / clear the interrupt character 
  5607                              <1> 			   ; / in the tty buffer
  5608                              <1> 		; br sysret4 / return to user
  5609                              <1> 
  5610                              <1> syssetuid: ; / set process id
  5611                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5612                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5613                              <1> 	;		(16 bit uid)
  5614                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5615                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  5616                              <1> 	;
  5617                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  5618                              <1> 	; to the process id in (u.r0). Both the effective user u.uid
  5619                              <1> 	; and the real user u.ruid are set to this. 
  5620                              <1> 	; Only the super user can make this call.	
  5621                              <1> 	;
  5622                              <1> 	; Calling sequence:
  5623                              <1> 	;	syssetuid
  5624                              <1> 	; Arguments: -
  5625                              <1> 	;
  5626                              <1> 	; Inputs: (u.r0) - contains the process id.
  5627                              <1> 	; Outputs: -
  5628                              <1> 	; ...............................................................
  5629                              <1> 	;	
  5630                              <1> 	; Retro UNIX 8086 v1 modification: 
  5631                              <1> 	;       BL contains the (new) user ID of the current process
  5632                              <1> 
  5633                              <1> 	; 27/03/2021
  5634                              <1> 	; INPUT:
  5635                              <1> 	;    BX = (new) user ID
  5636                              <1> 
  5637                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  5638                              <1> 	;cmp	bl, [u.ruid] 
  5639                              <1> 	;	; cmpb r1,u.ruid / is it equal to the real user 
  5640                              <1> 			       ; / id number
  5641                              <1> 	; 27/03/2021
  5642 000045FC 663B1D[B86D0000]    <1> 	cmp	bx, [u.ruid]
  5643 00004603 7420                <1> 	je	short setuid1
  5644                              <1> 		; beq 1f / yes
  5645                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  5646                              <1> 	;	; tstb u.uid / no, is current user the super user?
  5647                              <1> 	;;ja	error
  5648                              <1> 	;	; bne error4 / no, error
  5649                              <1> 	; 27/03/2021
  5650 00004605 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0 
  5651 0000460D 760F                <1> 	jna	short setuid0
  5652                              <1> setuid_err:
  5653                              <1> setgid_err:
  5654 0000460F C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  5654 00004617 0000                <1>
  5655                              <1> 				; 'permission denied !' error
  5656 00004619 E94FECFFFF          <1> 	jmp	error
  5657                              <1> setuid0:
  5658                              <1> 	;mov	[u.ruid], bl
  5659                              <1> 	; 27/03/2021
  5660 0000461E 66891D[B86D0000]    <1> 	mov	[u.ruid], bx
  5661                              <1> setuid1: ; 1:
  5662                              <1> 	;mov	[u.uid], bl ; 02/08/2013
  5663                              <1> 	;	; movb r1,u.uid / put process id in u.uid
  5664                              <1> 	;	; movb r1,u.ruid / put process id in u.ruid
  5665                              <1> 	; 27/03/2021
  5666 00004625 66891D[B66D0000]    <1> 	mov	[u.uid], bx
  5667 0000462C E95CECFFFF          <1> 	jmp	sysret
  5668                              <1> 		; br sysret4 / system return
  5669                              <1> 
  5670                              <1> sysgetuid: ; < get user id >
  5671                              <1> 	; 11/03/2022
  5672                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5673                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5674                              <1> 	;		(16 bit uid)
  5675                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5676                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5677                              <1> 	;
  5678                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  5679                              <1> 	; The real user ID identifies the person who is logged in,
  5680                              <1> 	; in contradistinction to the effective user ID, which
  5681                              <1> 	; determines his access permission at each moment. It is thus
  5682                              <1> 	; useful to programs which operate using the 'set user ID'
  5683                              <1> 	; mode, to find out who invoked them.	
  5684                              <1> 	;
  5685                              <1> 	; Calling sequence:
  5686                              <1> 	;	syssetuid
  5687                              <1> 	; Arguments: -
  5688                              <1> 	;
  5689                              <1> 	; Inputs: -
  5690                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  5691                              <1> 	; ...............................................................
  5692                              <1> 	;	
  5693                              <1> 	; Retro UNIX 8086 v1 modification: 
  5694                              <1> 	;       AL contains the real user ID at return.
  5695                              <1> 	;
  5696                              <1> 	; 11/03/2022 - Retro UNIX 386 v1.2
  5697                              <1> 	; Input:
  5698                              <1> 	;	none
  5699                              <1> 	; Output/Return:
  5700                              <1> 	;	AX = real user ID
  5701                              <1> 	;	Hig Word of EAX = effective user ID
  5702                              <1> 
  5703                              <1> 	;;movzx eax, byte [u.ruid]
  5704                              <1> 	; 27/03/2021
  5705                              <1> 	;movzx	eax, word [u.ruid]
  5706                              <1> 	; 11/03/2022
  5707                              <1> 	; (return u.uid & u.ruid numbers as it is in unix v5-v7)
  5708 00004631 66A1[B66D0000]      <1> 	mov	ax, [u.uid]
  5709 00004637 C1E010              <1> 	shl	eax, 16	; efective user ID in high word of eax
  5710                              <1> 	; 09/01/2022
  5711 0000463A 66A1[B86D0000]      <1> 	mov	ax, [u.ruid] ; real user ID in low word of eax
  5712 00004640 A3[646D0000]        <1> 	mov	[u.r0], eax 
  5713                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  5714 00004645 E943ECFFFF          <1> 	jmp	sysret
  5715                              <1> 		; br sysret4 / systerm return, sysret
  5716                              <1> 
  5717                              <1> syssetgid: ; set group id
  5718                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5719                              <1> 	; 02/04/2021
  5720                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5721                              <1> 	;
  5722                              <1> 	; 'syssetgid' sets the user's group id (u.gid) 
  5723                              <1> 	;  of the current process to the process id in (u.r0).
  5724                              <1> 	;  Both the effective user u.gid and the real user
  5725                              <1> 	;  u.rgid are set to this. 
  5726                              <1> 	;  Only the super user can make this call.	
  5727                              <1> 	
  5728                              <1> 	; INPUT:
  5729                              <1> 	;	BL = (new) group ID
  5730                              <1> 	; OUTPUT:
  5731                              <1> 	;	-
  5732                              <1> 
  5733 0000464A 3A1D[BB6D0000]      <1> 	cmp	bl, [u.rgid] 
  5734 00004650 7410                <1> 	je	short setgid1
  5735                              <1> 
  5736                              <1> 	;cmp	byte [u.uid], 0
  5737                              <1> 	; 02/04/2021
  5738 00004652 66833D[B66D0000]00  <1> 	cmp	word [u.uid], 0
  5739 0000465A 77B3                <1> 	ja	short setgid_err
  5740                              <1> setgid0:
  5741 0000465C 881D[BB6D0000]      <1> 	mov	[u.rgid], bl
  5742                              <1> setgid1: ; 1:
  5743 00004662 881D[BA6D0000]      <1> 	mov	[u.gid], bl
  5744 00004668 E920ECFFFF          <1> 	jmp	sysret
  5745                              <1> 
  5746                              <1> sysgetgid: ; < get group id >
  5747                              <1> 	; 11/03/2022
  5748                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5749                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5750                              <1> 	;
  5751                              <1> 	; 'sysgetgid' returns the real group ID of the current process.
  5752                              <1> 	; The real group ID identifies the group of the person
  5753                              <1> 	; who is logged in, in contradistinction to the effective
  5754                              <1> 	; group ID, which determines his access permission at each moment.
  5755                              <1> 	; It is thus useful to programs which operate using
  5756                              <1> 	; the 'set group ID' mode, to find out the group of the user
  5757                              <1> 	; who invoked them.
  5758                              <1> 
  5759                              <1> 	; 11/03/2022 - Retro UNIX 386 v1.2
  5760                              <1> 	; Input:
  5761                              <1> 	;	none
  5762                              <1> 	; Output/Return:
  5763                              <1> 	;	AL = real group ID
  5764                              <1> 	;	AH = effective group ID
  5765                              <1> 
  5766                              <1> 	;movzx	eax, word [u.ruid]
  5767                              <1> 	;; 09/01/2022
  5768                              <1> 	;mov	ax, [u.ruid]
  5769                              <1> 	; 11/03/2022
  5770                              <1> 	; (return u.gid & u.rgid numbers as it is in unix v5-v7)
  5771 0000466D 8A25[BA6D0000]      <1> 	mov	ah, [u.gid] ; efective group ID in byte 1
  5772 00004673 A0[BB6D0000]        <1> 	mov	al, [u.rgid] ; real group ID in byte 0
  5773 00004678 A3[646D0000]        <1> 	mov	[u.r0], eax
  5774 0000467D E90BECFFFF          <1> 	jmp	sysret
  5775                              <1> 
  5776                              <1> sysver: ; get operating system version
  5777                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5778                              <1> 	; 18/06/2021 - Retro UNIX 386 v2
  5779                              <1> 
  5780                              <1> 	;VMAJOR equ 2 ; Retro UNIX 386 v2
  5781                              <1> 	;VMINOR equ 0 ; Retro UNIX 386 v2.0 (v2.0.0)
  5782                              <1> 	;CURRENT_VERSION equ (VMAJOR*256)+VMINOR
  5783                              <1> 
  5784                              <1> 	; 09/01/2022
  5785                              <1> 	VMAJOR equ 1 ; Retro UNIX 386 v1
  5786                              <1> 	VMINOR equ 2 ; Retro UNIX 386 v1.2 (v1.2.0)
  5787                              <1> 	CURRENT_VERSION equ (VMAJOR*256)+VMINOR 		  
  5788                              <1> 
  5789                              <1> 	; 29/04/2016 - TRDOS 386 v2.0
  5790                              <1> 	;mov	dword [u.r0], 200h ; AH = major version, AL = minor version 
  5791                              <1> 	; 18/06/2021
  5792 00004682 C705[646D0000]0201- <1> 	mov	dword [u.r0], CURRENT_VERSION ;	(ah = 2, al = 0)
  5792 0000468A 0000                <1>
  5793 0000468C E9FCEBFFFF          <1> 	jmp	sysret
  5794                              <1> 
  5795                              <1> anyi: 
  5796                              <1> 	; 26/03/2022
  5797                              <1> 	; 13/03/2022
  5798                              <1> 	; 12/03/2022
  5799                              <1> 	; 09/01/2022
  5800                              <1> 	; 02/01/2022
  5801                              <1> 	; 01/01/2022
  5802                              <1> 	; 27/12/2021 (Retro UNIX 386 v1.2)
  5803                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  5804                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5805                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  5806                              <1> 	;
  5807                              <1> 	; 'anyi' is called if a file deleted while open.
  5808                              <1> 	; "anyi" checks to see if someone else has opened this file.
  5809                              <1> 	;
  5810                              <1> 	; INPUTS ->
  5811                              <1> 	;    r1 - contains an i-number
  5812                              <1> 	;    fsp - start of table containing open files
  5813                              <1> 	;
  5814                              <1> 	; OUTPUTS ->
  5815                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  5816                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  5817                              <1> 	;    if file not found - bit in i-node map is cleared
  5818                              <1> 	;    			 (i-node is freed)
  5819                              <1> 	;               all blocks related to i-node are freed
  5820                              <1> 	;	        all flags in i-node are cleared
  5821                              <1> 	; ((AX = R1)) input
  5822                              <1> 	;
  5823                              <1> 	;    (Retro UNIX Prototype: 02/12/2012, UNIXCOPY.ASM)
  5824                              <1> 	;	12/03/2022
  5825                              <1>         ;    ((Modified registers: eax, edx, ecx, ebx, esi, edi, ebp))  
  5826                              <1> 	;
  5827                              <1> 		; / r1 contains an i-number
  5828 00004691 BB[D4690000]        <1> 	mov	ebx, fsp
  5829                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  5830                              <1> anyi_1: ; 1:
  5831                              <1> 	;cmp	eax, [ebx] ; 09/01/2022 (32 bit inode number)
  5832 00004696 663B03              <1> 	cmp	ax, [ebx]
  5833                              <1> 		; cmp r1,(r2) / do i-numbers match?
  5834                              <1> 	;je	short anyi_3
  5835                              <1> 		; beq 1f / yes, 1f
  5836                              <1> 	; 12/03/2022
  5837 00004699 7505                <1> 	jne	short anyi_0		
  5838                              <1> 
  5839                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5840                              <1> 	;neg	ax
  5841                              <1> 	;	; neg r1 / no complement r1
  5842                              <1> 	;cmp	ax, [ebx]
  5843                              <1> 	;	; cmp r1,(r2) / do they match now?
  5844                              <1> 	;;je	short anyi_3
  5845                              <1> 		; beq 1f / yes, transfer
  5846                              <1> 		; / i-numbers do not match
  5847                              <1> 	; 12/03/2022
  5848                              <1> 	;jne	short ayni_0
  5849                              <1> 
  5850                              <1> anyi_3: ; 1: / i-numbers match
  5851                              <1> 	; 13/03/2022 (BugFix)
  5852                              <1> 	;; 09/01/2022
  5853                              <1> 	;test	byte [ebx+5], 1 ; open for writing flag
  5854                              <1> 	;jz	short anyi_0	
  5855                              <1> 
  5856                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5857 0000469B 804B0580            <1> 	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  5858                              <1> 	; 22/06/2015
  5859                              <1> 	;inc 	byte [ebx+9]
  5860                              <1> 		; incb 7(r2) / increment upper byte of the 4th word
  5861                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  5862 0000469F C3                  <1> 	retn
  5863                              <1> 		; rts r0
  5864                              <1> anyi_0:
  5865                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5866                              <1> 	;add	ebx, fp.size ; runix v2 fsp table size is 16 bytes
  5867                              <1> 	; 01/01/2022
  5868 000046A0 83C310              <1> 	add	ebx, 16 ; runix v2 fsp table size is 16 bytes
  5869                              <1> 	;;add	ebx, 10 ; fsp table size is 10 bytes
  5870                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  5871                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  5872                              <1> 	; 22/11/2021
  5873                              <1> 	;cmp	ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16)
  5874                              <1> 	; 02/01/2022
  5875 000046A3 81FB[F46C0000]      <1> 	cmp	ebx, fsp + (nfiles*16)
  5876                              <1> 	; 01/01/2022
  5877                              <1> 	;cmp	ebx, fsp + (NFILES*16) ; fsp+(NFILES*fp.size)
  5878                              <1> 	;;cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  5879                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  5880                              <1> 			; / are we at last entry in the table
  5881 000046A9 72EB                <1> 	jb	short anyi_1
  5882                              <1> 		; blt 1b / no, check next entries i-number
  5883                              <1> 
  5884                              <1> 	; 27/12/2021
  5885                              <1> 	;;cmp	ax, 32768
  5886                              <1> 	;cmp	ah, 80h ; negative number check
  5887                              <1> 	;	; tst r1 / yes, no match
  5888                              <1> 	;	; bge .+4
  5889                              <1> 	;jb	short anyi_2
  5890                              <1> 	;neg	ax
  5891                              <1> 	;	; neg r1 / make i-number positive
  5892                              <1> ;anyi_2:	
  5893                              <1> 	; 12/03/2022
  5894                              <1> 	;push	eax ; **** ; inode number
  5895                              <1> 	;
  5896 000046AB E8B4080000          <1> 	call	imap
  5897                              <1> 		; jsr r0,imap / get address of allocation bit 
  5898                              <1> 			    ; / in the i-map in r2
  5899                              <1> 
  5900                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  5901                              <1>         ;; EBX (R2) has address of the byte with allocation bit
  5902                              <1> 
  5903                              <1> 	; 12/03/2022
  5904                              <1> 	; (at return of imap)
  5905                              <1> 	; ebp = superblock buffer address
  5906                              <1> 	; eax = inode number
  5907                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5908                              <1> 	;			of current IMAP sector
  5909                              <1> 	; EBX = buffer address/offset for relevant alloc byte
  5910                              <1> 	;  DL has 1 at bit position which is for free inode
  5911                              <1> 	;
  5912                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5913                              <1> 
  5914                              <1>  	;;not	dx
  5915                              <1> 	;not 	dl ; 0 at calculated bit position, other bits are 1
  5916                              <1>         ;;and	[ebx], dx
  5917                              <1> 	;and 	[ebx], dl 
  5918                              <1> 	;	; bicb mq,(r2) / clear bit for i-node in the imap
  5919                              <1> 
  5920                              <1> 	; 12/03/2022 ; (*)
  5921                              <1> 
  5922                              <1> 	;mov	[ebp+SB.LastInode], eax ; (free) inode number
  5923                              <1> 
  5924 000046B0 50                  <1> 	push	eax ; ***
  5925 000046B1 51                  <1> 	push	ecx ; **
  5926 000046B2 52                  <1> 	push	edx ; *
  5927 000046B3 55                  <1> 	push	ebp ; @ ; 11/03/2022
  5928                              <1> 
  5929 000046B4 8B457C              <1> 	mov	eax, [ebp+SB.ImapBuffer]
  5930                              <1> 
  5931 000046B7 E836140000          <1> 	call	wslot
  5932                              <1> 	; ebx = buffer data address (write operation bit is set)
  5933                              <1> 	; eax = physical sector number
  5934                              <1> 	; Note: ebx contains addr of the 1st buffer in the buf chain
  5935                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  5936 000046BC 5D                  <1> 	pop	ebp ; @ ; 11/03/2022
  5937                              <1> 
  5938                              <1> 	;mov	[ebp+SB.ImapBuffer], ebx
  5939                              <1> 			; save inode map buffer address
  5940 000046BD 5A                  <1> 	pop	edx ; *
  5941 000046BE 59                  <1> 	pop	ecx ; **
  5942 000046BF 01CB                <1> 	add	ebx, ecx ; + byte offset (for allocation bit pos)	
  5943                              <1> 
  5944                              <1> 	;not	dx
  5945 000046C1 F6D2                <1> 	not 	dl ; 0 at calculated bit position, other bits are 1
  5946                              <1>         ;and	[ebx], dx
  5947 000046C3 2013                <1> 	and 	[ebx], dl 
  5948                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  5949                              <1> 
  5950                              <1> 	;push	ebp ; @
  5951 000046C5 E835140000          <1> 	call	dskwr ; writes the 1st buffer to sector
  5952                              <1> 		      ; (at the beginning/head of the buffer chain)
  5953                              <1> 	;pop	ebp ; @
  5954                              <1> 
  5955                              <1> 	; if we are here, buffer has been written to disk successfully 
  5956                              <1> 	; (otherwise cpu would jump to 'error' address)
  5957                              <1> 
  5958                              <1> 	; 12/03/2022 ; (*)
  5959                              <1> 	; set superblock modified flag
  5960 000046CA BA[566D0000]        <1> 	mov	edx, smod
  5961 000046CF F605[416D0000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  5962 000046D6 7401                <1> 	jz	short anyi_2 ; no, root device
  5963                              <1> 	; yes, mounted device
  5964 000046D8 42                  <1> 	inc	edx ; edx = offset mmod
  5965                              <1> anyi_2:
  5966 000046D9 FE02                <1> 	inc	byte [edx] ; superblock modified !
  5967                              <1> 
  5968                              <1> 	; 12/03/2022
  5969                              <1> 	; decrease first free inode number (if it is required)
  5970 000046DB 8B0424              <1> 	mov	eax, [esp] ; ***
  5971                              <1> 	; eax = released/freed inode number 
  5972 000046DE 394534              <1> 	cmp	[ebp+SB.FirstFreeIno], eax
  5973 000046E1 7603                <1> 	jna	short anyi_4
  5974 000046E3 894534              <1> 	mov	[ebp+SB.FirstFreeIno], eax
  5975                              <1> 		    ; (free inode search start value)
  5976                              <1> anyi_4:
  5977                              <1> 	; 12/03/2022
  5978                              <1> 	; increase free inode count
  5979 000046E6 8B5530              <1> 	mov	edx, [ebp+SB.FreeInodes]
  5980                              <1> 	;cmp	edx, 0FFFFFFFFh
  5981                              <1> 	;je	short anyi_5 ; invalid
  5982 000046E9 42                  <1> 	inc	edx ; 0FFFFFFFFh -> 0
  5983 000046EA 7403                <1> 	jz	short anyi_5 ; invalid
  5984 000046EC 895530              <1> 	mov	[ebp+SB.FreeInodes], edx ; +1
  5985                              <1> anyi_5:
  5986 000046EF E861150000          <1> 	call	get_system_time
  5987                              <1> 		; eax = current time (as unix epoch time)
  5988 000046F4 89455C              <1> 	mov	[ebp+SB.ModifTime], eax
  5989                              <1> 
  5990 000046F7 58                  <1> 	pop	eax ; *** ; inode number
  5991                              <1> 
  5992 000046F8 E863070000          <1> 	call	itrunc
  5993                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  5994                              <1> 
  5995                              <1> 	; 26/03/2022
  5996                              <1> 	; eax = 0 ; (itrunc clears eax at return)
  5997                              <1> 
  5998                              <1> 	; 12/03/2022
  5999                              <1> 	;pop	eax ; **** ; inode number
  6000                              <1> 
  6001                              <1> 	; 26/03/2022
  6002 000046FD 66A3[E4680000]      <1> 	mov	[i.flgs], ax ; (eax should be 0 here)
  6003                              <1> 	;mov 	word [i.flgs], 0
  6004                              <1> 		; clr i.flgs / clear all flags in the i-node
  6005 00004703 C3                  <1> 	retn
  6006                              <1> 		; rts r0 / return
  6007                              <1> 
  6008                              <1> ;anyi_3: ; 1: / i-numbers match
  6009                              <1> ;	; 09/01/2022
  6010                              <1> ;	test	byte [ebx+5], 1 ; open for writing flag
  6011                              <1> ;	jz	short anyi_0	
  6012                              <1> ;
  6013                              <1> ;	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  6014                              <1> ;	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  6015                              <1> ;	; 22/06/2015
  6016                              <1> ;	;inc 	byte [ebx+9]
  6017                              <1> ;		; incb 7(r2) / increment upper byte of the 4th word
  6018                              <1> ;		   ; / in that fsp entry (deleted flag of fsp entry)
  6019                              <1> ;	retn
  6020                              <1> ;		; rts r0
  2089                                  %include 'u3.s'      ; 10/05/2015
  2090                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2091                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2092                              <1> ; ****************************************************************************
  2093                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2094                              <1> ; Last Modification: 24/12/2021
  2095                              <1> ; ----------------------------------------------------------------------------
  2096                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2097                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2098                              <1> ;
  2099                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2100                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2101                              <1> ; <Bell Laboratories (17/3/1972)>
  2102                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2103                              <1> ;
  2104                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2105                              <1> ;
  2106                              <1> ; ****************************************************************************
  2107                              <1> 
  2108                              <1> tswitch: ; Retro UNIX 386 v1
  2109                              <1> tswap:
  2110                              <1> 	; 01/09/2015
  2111                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2112                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2113                              <1> 	; time out swap, called when a user times out.
  2114                              <1> 	; the user is put on the low priority queue.
  2115                              <1> 	; This is done by making a link from the last user
  2116                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2117                              <1> 	; then he is swapped out.
  2118                              <1> 	;
  2119                              <1> 	; Retro UNIX 386 v1 modification ->
  2120                              <1> 	;       swap (software task switch) is performed by changing
  2121                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2122                              <1> 	;	as in Retro UNIX 8086 v1.
  2123                              <1> 	;
  2124                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2125                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2126                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2127                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2128                              <1> 	;	compatibles was using 1MB segmented memory 
  2129                              <1> 	;	in 8086/8088 times.
  2130                              <1> 	;
  2131                              <1> 	; INPUTS ->
  2132                              <1> 	;    u.uno - users process number
  2133                              <1> 	;    runq+4 - lowest priority queue
  2134                              <1> 	; OUTPUTS ->
  2135                              <1> 	;    r0 - users process number
  2136                              <1> 	;    r2 - lowest priority queue address
  2137                              <1> 	;
  2138                              <1> 	; ((AX = R0, BX = R2)) output
  2139                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2140                              <1> 	;
  2141 00004704 A0[B56D0000]        <1> 	mov 	al, [u.uno]
  2142                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2143                              <1> 		; mov  $runq+4,r2 
  2144                              <1> 			; / move lowest priority queue address to r2
  2145 00004709 E8CD000000          <1>         call 	putlu
  2146                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2147                              <1> 		             ; / u.uno's user
  2148                              <1> 
  2149                              <1> switch: ; Retro UNIX 386 v1
  2150                              <1> swap:
  2151                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2152                              <1> 	; 02/09/2015
  2153                              <1> 	; 01/09/2015
  2154                              <1> 	; 31/08/2015
  2155                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2156                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2157                              <1> 	; 'swap' is routine that controls the swapping of processes
  2158                              <1> 	; in and out of core.
  2159                              <1> 	;
  2160                              <1> 	; Retro UNIX 386 v1 modification ->
  2161                              <1> 	;       swap (software task switch) is performed by changing
  2162                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2163                              <1> 	;	as in Retro UNIX 8086 v1.
  2164                              <1> 	;
  2165                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2166                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2167                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2168                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2169                              <1> 	;	compatibles was using 1MB segmented memory 
  2170                              <1> 	;	in 8086/8088 times.
  2171                              <1> 	;
  2172                              <1> 	; INPUTS ->
  2173                              <1> 	;    runq table - contains processes to run.
  2174                              <1> 	;    p.link - contains next process in line to be run.
  2175                              <1> 	;    u.uno - process number of process in core	
  2176                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2177                              <1> 	; OUTPUTS ->
  2178                              <1> 	;    (original unix v1 -> present process to its disk block)
  2179                              <1> 	;    (original unix v1 -> new process into core -> 
  2180                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2181                              <1> 	;	   for new process)
  2182                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2183                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2184                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2185                              <1> 	;	 for now, it will swap the process if there is not
  2186                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2187                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2188                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2189                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2190                              <1> 	;
  2191                              <1> 	;    u.pri -points to highest priority run Q.
  2192                              <1> 	;    r2 - points to the run queue.
  2193                              <1> 	;    r1 - contains new process number
  2194                              <1> 	;    r0 - points to place in routine or process that called
  2195                              <1> 	;	  swap all user parameters
  2196                              <1> 	;				
  2197                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2198                              <1> 	;
  2199                              <1> swap_0:
  2200                              <1> 		;mov $300,*$ps / processor priority = 6
  2201 0000470E BE[526D0000]        <1> 	mov	esi, runq
  2202                              <1> 		; mov $runq,r2 / r2 points to runq table
  2203                              <1> swap_1: ; 1: / search runq table for highest priority process
  2204 00004713 668B06              <1> 	mov	ax, [esi]
  2205 00004716 6621C0              <1> 	and 	ax, ax
  2206                              <1>        		; tst (r2)+ / are there any processes to run 
  2207                              <1> 			  ; / in this Q entry
  2208 00004719 7507                <1> 	jnz	short swap_2
  2209                              <1>        		; bne 1f / yes, process 1f
  2210                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2211                              <1> 			       ; / to end of table
  2212                              <1> 		; bne 1b / if not at end, go back
  2213 0000471B E8E0000000          <1> 	call	idle
  2214                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2215                              <1> 				       ; / all queues are empty
  2216 00004720 EBF1                <1> 	jmp	short swap_1
  2217                              <1> 		; br swap
  2218                              <1> swap_2: ; 1:
  2219 00004722 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2220                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2221                              <1>  		; mov r2,u.pri / set present user to this run queue
  2222                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2223 00004725 38E0                <1> 	cmp	al, ah
  2224                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2225                              <1> 			      ; / in this Q to be run
  2226 00004727 740A                <1> 	je	short swap_3
  2227                              <1>        		; beq 1f / yes
  2228                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2229                              <1> 	;movzx	ebx, al
  2230 00004729 8AA3[73690000]      <1> 	mov	ah, [ebx+p.link-1] 
  2231 0000472F 8826                <1>        	mov	[esi], ah
  2232                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2233                              <1> 				       ; / in line into run queue
  2234 00004731 EB05                <1> 	jmp	short swap_4
  2235                              <1>        		; br 2f
  2236                              <1> swap_3: ; 1:
  2237                              <1> 	;xor	dx, dx
  2238                              <1> 	; 24/12/2021
  2239 00004733 31D2                <1> 	xor	edx, edx
  2240 00004735 668916              <1> 	mov	[esi], dx
  2241                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2242                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2243                              <1>       ; / in new process if required
  2244                              <1>        		; clr *$ps / clear processor status
  2245 00004738 8A25[B56D0000]      <1> 	mov 	ah, [u.uno]
  2246 0000473E 38C4                <1> 	cmp	ah, al
  2247                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2248                              <1> 			      ; / the process in core?
  2249 00004740 743B                <1>        	je	short swap_8
  2250                              <1>        		; beq 2f / yes, don't have to swap
  2251                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2252                              <1> 			   ; / (address in routine that called swap)
  2253                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2254                              <1> 	; 01/09/2015
  2255                              <1> 	;mov	[u.usp], esp
  2256                              <1>        		; mov sp,u.usp / save stack pointer
  2257                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2258                              <1> 			       ; / to the stack pointer
  2259 00004742 08E4                <1> 	or	ah, ah
  2260                              <1>        		; tstb u.uno / is the process # = 0
  2261 00004744 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2262                              <1> 		; beq  1f / yes, kill process by overwriting
  2263                              <1> 	; 02/09/2015
  2264 00004746 8925[606D0000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2265                              <1> 	;
  2266 0000474C E834000000          <1> 	call	wswap
  2267                              <1> 		;jsr r0,wswap / write out core to disk
  2268                              <1> 	 ; 31/08/2015
  2269                              <1> 	;movzx	ebx, al ; New (running) process number
  2270 00004751 EB1C                <1> 	jmp 	short swap_7
  2271                              <1> swap_6:
  2272                              <1> 	; 31/08/2015
  2273                              <1> 	; Deallocate memory pages belong to the process
  2274                              <1> 	; which is being terminated
  2275                              <1> 	; 14/05/2015 ('sysexit')
  2276                              <1>  	; Deallocate memory pages of the process
  2277                              <1> 	; (Retro UNIX 386 v1 modification !)
  2278                              <1> 	;
  2279                              <1> 	; movzx ebx, al
  2280 00004753 53                  <1> 	push	ebx
  2281 00004754 A1[C46D0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2282 00004759 8B1D[C86D0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2283 0000475F E8B0DEFFFF          <1> 	call	deallocate_page_dir
  2284 00004764 A1[C06D0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2285 00004769 E83EDFFFFF          <1> 	call	deallocate_page
  2286 0000476E 5B                  <1> 	pop	ebx
  2287                              <1> swap_7: ;1: 
  2288                              <1> 	; 02/09/2015
  2289                              <1> 	; 31/08/2015
  2290                              <1> 	; 14/05/2015
  2291 0000476F C0E302              <1> 	shl	bl, 2 ; * 4 
  2292 00004772 8B83[90690000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2293                              <1> 	;cli
  2294 00004778 E831000000          <1> 	call	rswap
  2295                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2296                              <1> 		; jsr r0,rswap / read new process into core
  2297                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2298                              <1> 			      ; / to his program to its normal
  2299                              <1> 	; 01/09/2015
  2300                              <1> 	;mov	esp, [u.usp]	
  2301                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2302                              <1> 			     ; / new process stack
  2303                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2304                              <1> 			     ; / that just got swapped in, left off.,
  2305                              <1> 			     ; / i.e., transfer control to new process
  2306                              <1> 	;sti
  2307                              <1> swap_8: ;2:
  2308                              <1> 	; RETRO UNIX 8086 v1 modification !
  2309 0000477D C605[AC6D0000]04    <1> 	mov	byte [u.quant], time_count 
  2310                              <1> 		; movb $30.,uquant / initialize process time quantum
  2311 00004784 C3                  <1> 	retn
  2312                              <1> 		; rts r0 / return
  2313                              <1> 
  2314                              <1> wswap:  ; < swap out, swap to disk >
  2315                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2316                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2317                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2318                              <1> 	; appropriate disk area.
  2319                              <1> 	;
  2320                              <1> 	; Retro UNIX 386 v1 modification ->
  2321                              <1> 	;       User (u) structure content and the user's register content
  2322                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2323                              <1> 	;	saving 'u' structure and user registers for task switching).
  2324                              <1> 	;	u.usp - points to kernel stack address which contains
  2325                              <1> 	;		user's registers while entering system call.  
  2326                              <1> 	;	u.sp  - points to kernel stack address 
  2327                              <1> 	;		to return from system call -for IRET-.
  2328                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2329                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2330                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2331                              <1> 	;
  2332                              <1> 	; Retro UNIX 8086 v1 modification ->
  2333                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2334                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2335                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2336                              <1> 	;	compatibles was using 1MB segmented memory 
  2337                              <1> 	;	in 8086/8088 times.
  2338                              <1> 	;
  2339                              <1> 	; INPUTS ->
  2340                              <1> 	;    u.break - points to end of program
  2341                              <1> 	;    u.usp - stack pointer at the moment of swap
  2342                              <1> 	;    core - beginning of process program		
  2343                              <1> 	;    ecore - end of core 	
  2344                              <1> 	;    user - start of user parameter area		
  2345                              <1> 	;    u.uno - user process number	
  2346                              <1> 	;    p.dska - holds block number of process	
  2347                              <1> 	; OUTPUTS ->
  2348                              <1> 	;    swp I/O queue
  2349                              <1> 	;    p.break - negative word count of process 
  2350                              <1> 	;    r1 - process disk address	
  2351                              <1> 	;    r2 - negative word count
  2352                              <1> 	;
  2353                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2354                              <1> 	;
  2355                              <1> 	; INPUTS ->
  2356                              <1> 	;    u.uno - process number (to be swapped out)
  2357                              <1> 	; OUTPUTS ->
  2358                              <1> 	;    none
  2359                              <1> 	;
  2360                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2361                              <1> 	;
  2362 00004785 8B3D[C06D0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2363 0000478B B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2364 00004790 BE[5C6D0000]        <1> 	mov	esi, user ; active user (u) structure	
  2365 00004795 F3A5                <1> 	rep	movsd
  2366                              <1> 	;
  2367 00004797 8B35[606D0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2368                              <1> 			     ;      points to user registers)
  2369 0000479D 8B0D[5C6D0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2370                              <1> 			     ; (for IRET)
  2371                              <1> 			     ; [u.sp] -> EIP (user)
  2372                              <1> 			     ; [u.sp+4]-> CS (user)
  2373                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2374                              <1> 			     ; [u.sp+12] -> ESP (user)
  2375                              <1> 			     ; [u.sp+16] -> SS (user)	
  2376 000047A3 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2377 000047A5 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2378                              <1> 			     ; (for IRET) 	
  2379 000047A8 C1E902              <1> 	shr	ecx, 2	     		
  2380 000047AB F3A5                <1> 	rep	movsd
  2381 000047AD C3                  <1> 	retn
  2382                              <1> 
  2383                              <1> 	; Original UNIX v1 'wswap' routine:
  2384                              <1> 	; wswap:
  2385                              <1> 		; mov *$30,u.emt / determines handling of emts
  2386                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2387                              <1> 				; / illegal instructions
  2388                              <1> 		; mov u.break,r2 / put process program break address in r2
  2389                              <1> 		; inc r2 / add 1 to it 
  2390                              <1> 		; bic $1,r2 / make it even
  2391                              <1> 		; mov r2,u.break / set break to an even location
  2392                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2393                              <1> 			     ; / at moment of swap in r3
  2394                              <1> 		; cmp r2,$core / is u.break less than $core
  2395                              <1> 		; blos 2f / yes
  2396                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2397                              <1>        		; bhis 2f / yes
  2398                              <1> 	; 1:
  2399                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2400                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2401                              <1> 		; bne 1b / no, keep packing
  2402                              <1> 	 	; br 1f / yes
  2403                              <1> 	; 2:
  2404                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2405                              <1> 	; 1:
  2406                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2407                              <1> 			   ; / (user up to end of stack gets written out)
  2408                              <1> 		; neg r2 / make it negative
  2409                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2410                              <1> 		; mov r2,swp+4 / word count
  2411                              <1> 		; movb u.uno,r1 / move user process number to r1
  2412                              <1> 		; asl r1 / x2 for index
  2413                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2414                              <1> 				     ; / into the p.break table
  2415                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2416                              <1> 				    ; /	for process to r1
  2417                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2418                              <1> 			     ; / (block number)
  2419                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2420                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2421                              <1> 	; 1:
  2422                              <1>        		; tstb swp+1 / is lt done writing?
  2423                              <1>        		; bne 1b / no, wait
  2424                              <1> 		; rts r0 / yes, return to swap
  2425                              <1> 
  2426                              <1> rswap:  ; < swap in, swap from disk >
  2427                              <1> 	; 15/09/2015
  2428                              <1> 	; 28/08/2015
  2429                              <1> 	; 14/05/2015
  2430                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2431                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2432                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2433                              <1> 	; from disk into core.
  2434                              <1> 	;
  2435                              <1> 	; Retro UNIX 386 v1 modification ->
  2436                              <1> 	;       User (u) structure content and the user's register content
  2437                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2438                              <1> 	;	saving 'u' structure and user registers for task switching).
  2439                              <1> 	;	u.usp - points to kernel stack address which contains
  2440                              <1> 	;		user's registers while entering system call.  
  2441                              <1> 	;	u.sp  - points to kernel stack address 
  2442                              <1> 	;		to return from system call -for IRET-.
  2443                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2444                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2445                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2446                              <1> 	;
  2447                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2448                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2449                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2450                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2451                              <1> 	;	compatibles was using 1MB segmented memory 
  2452                              <1> 	;	in 8086/8088 times.
  2453                              <1> 	;
  2454                              <1> 	; INPUTS ->
  2455                              <1> 	;    r1 - process number of process to be read in
  2456                              <1> 	;    p.break - negative of word count of process 
  2457                              <1> 	;    p.dska - disk address of the process		
  2458                              <1> 	;    u.emt - determines handling of emt's 	
  2459                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2460                              <1> 	; OUTPUTS ->
  2461                              <1> 	;    8 = (u.ilgins)
  2462                              <1> 	;    24 = (u.emt)
  2463                              <1> 	;    swp - bit 10 is set to indicate read 
  2464                              <1> 	;		(bit 15=0 when reading is done)	
  2465                              <1> 	;    swp+2 - disk block address
  2466                              <1> 	;    swp+4 - negative word count 	
  2467                              <1> 	;      ((swp+6 - address of user structure)) 
  2468                              <1> 	;
  2469                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2470                              <1> 	;
  2471                              <1> 	; INPUTS ->
  2472                              <1> 	;    AL	- new process number (to be swapped in)	 
  2473                              <1> 	; OUTPUTS ->
  2474                              <1> 	;    none
  2475                              <1> 	;
  2476                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2477                              <1> 	;
  2478                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2479 000047AE 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2480 000047B0 B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2481 000047B5 BF[5C6D0000]        <1> 	mov	edi, user ; active user (u) structure	
  2482 000047BA F3A5                <1> 	rep	movsd
  2483 000047BC 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2484 000047BD 8B3D[606D0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2485                              <1> 			     ;      points to user registers)
  2486 000047C3 8B0D[5C6D0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2487                              <1> 			     ; (for IRET)
  2488                              <1> 			     ; [u.sp] -> EIP (user)
  2489                              <1> 			     ; [u.sp+4]-> CS (user)
  2490                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2491                              <1> 			     ; [u.sp+12] -> ESP (user)
  2492                              <1> 			     ; [u.sp+16] -> SS (user)		
  2493                              <1> 	; 28/08/2015
  2494 000047C9 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2495 000047CB 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2496                              <1> 			     ; (for IRET) 	
  2497 000047CE C1E902              <1> 	shr	ecx, 2	       		
  2498 000047D1 F3A5                <1> 	rep	movsd
  2499 000047D3 8B25[606D0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2500 000047D9 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2501 000047DA C3                  <1> 	retn
  2502                              <1> 
  2503                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2504                              <1> 	;rswap:
  2505                              <1>        		; asl r1 / process number x2 for index
  2506                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2507                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2508                              <1>        		; bis $2000,swp / read
  2509                              <1>        		; jsr r0,ppoke / read it in 
  2510                              <1> 	; 1:
  2511                              <1>        		; tstb swp+1 / done
  2512                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2513                              <1>        		; mov u.emt,*$30 / yes move these
  2514                              <1>        		; mov u.ilgins,*$10 / back
  2515                              <1>        		; rts r0 / return
  2516                              <1> 
  2517                              <1> 	;unpack: ; / move stack back to its normal place
  2518                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2519                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2520                              <1> 		; blos 2f / yes, return
  2521                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2522                              <1> 			     ; / before swapping
  2523                              <1> 		; bhis 2f / yes, return
  2524                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2525                              <1> 		; add r3,r2
  2526                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2527                              <1> 	; 1:
  2528                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2529                              <1> 		; cmp r2,u.break / in core
  2530                              <1> 		; bne 1b
  2531                              <1> 	; 2:
  2532                              <1>        		; rts r0
  2533                              <1> 
  2534                              <1> putlu: 
  2535                              <1> 	; 12/09/2015
  2536                              <1> 	; 02/09/2015
  2537                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2538                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2539                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2540                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2541                              <1> 	; the last process on the queue to process in r1 by putting
  2542                              <1> 	; the process number in r1 into the last process's link.
  2543                              <1> 	;
  2544                              <1> 	; INPUTS ->
  2545                              <1> 	;    r1 - user process number
  2546                              <1> 	;    r2 - points to lowest priority queue 
  2547                              <1> 	;    p.dska - disk address of the process		
  2548                              <1> 	;    u.emt - determines handling of emt's 	
  2549                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2550                              <1> 	; OUTPUTS ->
  2551                              <1> 	;    r3 - process number of last process on the queue upon
  2552                              <1> 	;	  entering putlu
  2553                              <1> 	;    p.link-1 + r3 - process number in r1
  2554                              <1> 	;    r2 - points to lowest priority queue
  2555                              <1> 	;
  2556                              <1> 	; ((Modified registers: EDX, EBX)) 
  2557                              <1> 	;
  2558                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2559                              <1> 
  2560                              <1> 	; eBX = r2
  2561                              <1> 	; eAX = r1 (AL=r1b)
  2562                              <1> 
  2563 000047DB BB[526D0000]        <1> 	mov	ebx, runq
  2564 000047E0 0FB613              <1> 	movzx  	edx, byte [ebx]
  2565 000047E3 43                  <1> 	inc	ebx
  2566 000047E4 20D2                <1> 	and	dl, dl
  2567                              <1> 		; tstb (r2)+ / is queue empty?
  2568 000047E6 740A                <1>        	jz	short putlu_1
  2569                              <1> 		; beq 1f / yes, branch
  2570 000047E8 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2571                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2572                              <1> 			     ; / in r3
  2573 000047EA 8882[73690000]      <1>        	mov	[edx+p.link-1], al
  2574                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2575                              <1> 			     ; / "last users" link
  2576 000047F0 EB03                <1> 	jmp	short putlu_2
  2577                              <1> 		; br 2f /
  2578                              <1> putlu_1: ; 1:
  2579 000047F2 8843FF              <1> 	mov	[ebx-1], al
  2580                              <1>        		; movb r1,-1(r2) / user is only user; 
  2581                              <1> 			    ; / put process no. at beginning and at end
  2582                              <1> putlu_2: ; 2: 
  2583 000047F5 8803                <1> 	mov	[ebx], al
  2584                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2585                              <1> 			     ; / on the queue
  2586 000047F7 88C2                <1> 	mov	dl, al
  2587 000047F9 88B2[73690000]      <1>         mov     [edx+p.link-1], dh ; 0
  2588                              <1> 		; dec r2 / restore r2
  2589 000047FF C3                  <1>         retn
  2590                              <1> 		; rts r0
  2591                              <1> 
  2592                              <1> ;copyz:
  2593                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2594                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2595                              <1> ;       mov     (r0)+,r1
  2596                              <1> ;       mov     (r0)+,r2
  2597                              <1> ;1:
  2598                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2599                              <1> ;       cmp     r1,r2 
  2600                              <1> ;       blo     1b
  2601                              <1> ;       mov     (sp)+,r2 / restore r2
  2602                              <1> ;       mov     (sp)+,r1 / restore r1
  2603                              <1> ;       rts     r0 
  2604                              <1> 
  2605                              <1> idle:
  2606                              <1> 	; 01/09/2015
  2607                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2608                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2609                              <1> 	; (idle & wait loop)
  2610                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2611                              <1> 	; idle procedure!
  2612                              <1>       	;
  2613                              <1>   	; 01/09/2015
  2614 00004800 FB                  <1> 	sti
  2615                              <1>       	; 29/07/2013
  2616 00004801 F4                  <1>       	hlt
  2617 00004802 90                  <1>       	nop ; 10/10/2013
  2618 00004803 90                  <1>       	nop
  2619 00004804 90                  <1>       	nop
  2620                              <1>       	; 23/10/2013
  2621 00004805 90                  <1>       	nop
  2622 00004806 90                  <1>       	nop
  2623 00004807 90                  <1>       	nop
  2624 00004808 90                  <1>       	nop
  2625 00004809 C3                  <1>       	retn      
  2626                              <1> 
  2627                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2628                              <1> 	;clr *$ps / clear ps
  2629                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2630                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2631                              <1> 	;1 / wait for interrupt
  2632                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2633                              <1> 	;mov (sp)+,*$ps
  2634                              <1> 	;rts r0
  2635                              <1> 
  2636                              <1> clear:
  2637                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2638                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2639                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2640                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2641                              <1> 	; on the current device (cdev)
  2642                              <1> 	;	
  2643                              <1> 	; INPUTS ->
  2644                              <1> 	;    r1 - block number of block to be zeroed
  2645                              <1> 	;    cdev - current device number 
  2646                              <1> 	; OUTPUTS ->
  2647                              <1> 	;    a zeroed I/O buffer onto the current device
  2648                              <1> 	;    r1 - points to last entry in the I/O buffer
  2649                              <1> 	;
  2650                              <1> 	; ((AX = R1)) input/output
  2651                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2652                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2653                              <1> 
  2654 0000480A E8E3120000          <1> 	call 	wslot
  2655                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2656                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2657 0000480F 89DF                <1> 	mov	edi, ebx ; r5
  2658 00004811 89C2                <1> 	mov	edx, eax
  2659 00004813 B980000000          <1> 	mov	ecx, 128
  2660                              <1> 		; mov $256.,r3
  2661 00004818 31C0                <1> 	xor	eax, eax
  2662 0000481A F3AB                <1> 	rep	stosd
  2663 0000481C 89D0                <1> 	mov	eax, edx
  2664                              <1> ; 1: 
  2665                              <1>        		; clr (r5)+ / zero data word in buffer
  2666                              <1>        		; dec r3
  2667                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2668                              <1> 	;call	dskwr
  2669                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2670                              <1>                              ; / block specified in r1
  2671                              <1> 	; eAX (r1) = block number
  2672                              <1> 	;retn
  2673                              <1> 		; rts r0
  2674                              <1> 	; 24/12/2021
  2675 0000481E E9DC120000          <1> 	jmp	dskwr
  2090                                  %include 'u4.s'      ; 15/04/2015
  2091                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2092                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2093                              <1> ; ****************************************************************************
  2094                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2095                              <1> ; Last Modification: 27/02/2022 (Retro UNIX 386 v1.2)
  2096                              <1> ; ----------------------------------------------------------------------------
  2097                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2098                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2099                              <1> ;
  2100                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2101                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2102                              <1> ; <Bell Laboratories (17/3/1972)>
  2103                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2104                              <1> ;
  2105                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2106                              <1> ;
  2107                              <1> ; ****************************************************************************
  2108                              <1> 
  2109                              <1> ;setisp:
  2110                              <1>        ;mov     r1,-(sp)
  2111                              <1>        ;mov     r2,-(sp)
  2112                              <1>        ;mov     r3,-(sp)
  2113                              <1>        ;mov     clockp,-(sp)
  2114                              <1>        ;mov     $s.syst+2,clockp
  2115                              <1>        ;jmp     (r0)
  2116                              <1> 
  2117                              <1> clock: ; / interrupt from 60 cycle clock
  2118                              <1> 	
  2119                              <1> 	; 14/10/2015
  2120                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2121                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2122                              <1> 
  2123                              <1>        ;mov     r0,-(sp) / save r0
  2124                              <1>        ;tst     *$lks / restart clock?
  2125                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2126                              <1>        ;inc     (r0)
  2127                              <1>        ;bne     1f
  2128                              <1>        ;inc     -(r0)
  2129                              <1> ;1:
  2130                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2131                              <1>        ;inc     (r0)
  2132                              <1>        ;bne     1f
  2133                              <1>        ;inc     -(r0)
  2134                              <1> ;1:
  2135                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2136                              <1> 
  2137 00004823 803D[AC6D0000]00    <1> 	cmp	byte [u.quant], 0
  2138 0000482A 772C                <1> 	ja	short clk_1
  2139                              <1> 	;
  2140 0000482C 803D[586D0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2141 00004833 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2142 00004835 803D[B56D0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2143 0000483C 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2144 0000483E 66833D[B06D0000]00  <1> 	cmp	word [u.intr], 0
  2145 00004846 7616                <1> 	jna	short clk_2
  2146                              <1> clk_0:
  2147                              <1> 	; 14/10/2015
  2148 00004848 FE05[586D0000]      <1> 	inc	byte [sysflg] ; Now, we are in system space
  2149 0000484E 58                  <1> 	pop	eax ; return address to the timer interrupt
  2150                              <1> 	;
  2151 0000484F B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2152                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2153 00004851 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2154                              <1> 	;
  2155 00004853 E99AEAFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2156                              <1> clk_1:
  2157 00004858 FE0D[AC6D0000]      <1> 	dec	byte [u.quant]
  2158                              <1> clk_2:
  2159 0000485E C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2160                              <1> 
  2161                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2162                              <1> 
  2163                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2164                              <1>        ;decb    (r0)
  2165                              <1>        ;bge     1f / if less than 0
  2166                              <1>        ;clrb    (r0) / make it 0
  2167                              <1> ;1: / decrement time out counts return now if priority was not 0
  2168                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2169                              <1>        ;bge     2f / yes, check time outs
  2170                              <1>        ;tstb    (r0) / no, user timed out?
  2171                              <1>        ;bne     1f / no
  2172                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2173                              <1>        ;bne     1f / no, 1f
  2174                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2175                              <1>        ;sys     0 / sysrele
  2176                              <1>        ;rti
  2177                              <1> ;2: / priority is high so just decrement time out counts
  2178                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2179                              <1> ;2:
  2180                              <1>        ;tstb    (r0) / is the time out?
  2181                              <1>        ;beq     3f / yes, 3f (get next entry)
  2182                              <1>        ;decb    (r0) / no, decrement the time
  2183                              <1>        ;bne     3f / isit zero now?
  2184                              <1>        ;incb    (r0) / yes, increment the time
  2185                              <1> ;3:
  2186                              <1>        ;inc     r0 / next entry
  2187                              <1>        ;cmp     r0,$touts / end of toutt table?
  2188                              <1>        ;blo     2b / no, check this entry
  2189                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2190                              <1>        ;rti / return from interrupt
  2191                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2192                              <1>        ;mov     (sp)+,r0 / restore r0
  2193                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2194                              <1>        ;jsr     r0,setisp / save registers
  2195                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2196                              <1>                                ;  / the table
  2197                              <1> ;1:
  2198                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2199                              <1>        ;beq     2f / yes
  2200                              <1>        ;decb    toutt(r0) / no, decrement the time
  2201                              <1>        ;bne     2f / is the time 0, now
  2202                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2203                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2204                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2205                              <1> ;2:
  2206                              <1>        ;dec     r0 / set up r0 for next entry
  2207                              <1>        ;bge     1b / finished? , no, go back
  2208                              <1>        ;br      retisp / yes, restore registers and do a rti
  2209                              <1> 
  2210                              <1> ;retisp:
  2211                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2212                              <1>        ;mov     (sp)+,r3
  2213                              <1>        ;mov     (sp)+,r2
  2214                              <1>        ;mov     (sp)+,r1
  2215                              <1>        ;mov     (sp)+,r0
  2216                              <1>        ;rti     / return from interrupt
  2217                              <1> 
  2218                              <1> 
  2219                              <1> wakeup: ; / wakeup processes waiting for an event 
  2220                              <1> 	; / by linking them to the queue
  2221                              <1> 	;
  2222                              <1> 	; 27/02/2022
  2223                              <1> 	; 15/09/2015
  2224                              <1> 	; 29/06/2015
  2225                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2226                              <1> 	;
  2227                              <1> 	; 15/05/2013 - 02/06/2014
  2228                              <1> 	; Retro UNIX 8086 v1 modification !
  2229                              <1> 	; (Process/task switching routine by using
  2230                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2231                              <1> 	;
  2232                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2233                              <1> 	; sleeping in the specified wait channel by creating a link 
  2234                              <1> 	; to it from the last user process on the run queue.
  2235                              <1> 	; If there is no process to wake up, nothing happens.
  2236                              <1> 	;
  2237                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2238                              <1> 	; 'switching' status of the current process (owns current tty)
  2239                              <1> 	; (via alt + function keys) to a process which has highest
  2240                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2241                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2242                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2243                              <1> 	; tty for tty switching by keyboard.)	 
  2244                              <1> 	; 
  2245                              <1> 	; INPUT -> 
  2246                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2247                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2248                              <1> 	;
  2249                              <1> 	; ((modified registers: EAX, EBX))
  2250                              <1> 	;
  2251 0000485F 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2252 00004862 81C3[88680000]      <1> 	add	ebx, wlist
  2253 00004868 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2254 0000486A 20C0                <1> 	and	al, al
  2255 0000486C 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2256                              <1> 	;
  2257 0000486E 30E4                <1> 	xor	ah, ah
  2258 00004870 8825[AC6D0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2259 00004876 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2260                              <1> 	; 15/09/2015
  2261 00004878 0FB6D8              <1> 	movzx	ebx, al
  2262                              <1> 	; 27/02/2022 (p.waitc is not used)
  2263                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2264 0000487B FEC4                <1> 	inc	ah
  2265 0000487D 88A3[83690000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2266                              <1> 	;
  2267 00004883 57                  <1> 	push	edi
  2268 00004884 52                  <1> 	push	edx
  2269 00004885 E851FFFFFF          <1> 	call	putlu
  2270 0000488A 5A                  <1> 	pop	edx
  2271 0000488B 5F                  <1> 	pop	edi
  2272                              <1> wa0:
  2273 0000488C C3                  <1> 	retn
  2274                              <1> 
  2275                              <1> 	; 27/02/2022
  2276                              <1> 	; 05/12/2021
  2277                              <1> 	; 30/11/2021 - Retro UNIX 386 v1.2
  2278                              <1> sleep: 
  2279                              <1> 	; 15/09/2015
  2280                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2281                              <1> 	;
  2282                              <1> 	; 09/05/2013 - 20/03/2014
  2283                              <1> 	;
  2284                              <1> 	; Retro UNIX 8086 v1 modification !
  2285                              <1> 	; (Process/task switching and quit routine by using
  2286                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2287                              <1> 	;
  2288                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2289                              <1> 	; tty and tape output or input becomes available
  2290                              <1> 	; and process is put on waiting channel and swapped out,
  2291                              <1> 	; then -when the tty or tape is ready to write or read-
  2292                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2293                              <1> 	;
  2294                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2295                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2296                              <1> 	; status of the current process also INT 1Ch will count down
  2297                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2298                              <1> 	; to tty buffer of the current process and kernel will get
  2299                              <1> 	; user input by using tty buffer of the current process
  2300                              <1> 	; (instead of standard INT 16h interrupt).
  2301                              <1> 	; TTY output will be redirected to related video page of text mode
  2302                              <1> 	; (INT 10h will be called with different video page depending
  2303                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2304                              <1> 	; pseudo screens.)
  2305                              <1> 	;
  2306                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2307                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2308                              <1> 	; characters/data on serial port(s).
  2309                              <1> 	;
  2310                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2311                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2312                              <1> 	; 
  2313                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2314                              <1> 	;
  2315                              <1> 	;; 05/10/2013
  2316                              <1>         ;10/12/2013
  2317                              <1> 	;cmp   byte [u.uno], 1
  2318                              <1>         ;ja    short sleep0
  2319                              <1> 	;retn
  2320                              <1> 
  2321                              <1> 	; 20/03/2014
  2322                              <1> 	;mov	bx, [runq]
  2323                              <1> 	;cmp	bl, bh
  2324                              <1> 	;jne	short sleep0	
  2325                              <1> 	; 25/02/2014
  2326                              <1> 	;cmp	word ptr [runq], 0
  2327                              <1> 	;ja	short sleep0	
  2328                              <1> 	;retn
  2329                              <1> sleep0:
  2330                              <1> 	;
  2331 0000488D E849000000          <1> 	call	isintr
  2332                              <1> 	;jnz	sysret
  2333                              <1> 		; / wait for event
  2334                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2335                              <1> 			      ; / or quit from user
  2336                              <1>                		; br 2f / something happened
  2337                              <1> 			      ; / yes, his interrupt so return
  2338                              <1>                      	      ;	/ to user
  2339                              <1> 	; 05/12/2021
  2340 00004892 7405                <1> 	jz	short sleep_2
  2341                              <1> sleep_3:
  2342 00004894 E9F4E9FFFF          <1> 	jmp	sysret
  2343                              <1> sleep_2:
  2344                              <1> 	; 30/06/2015
  2345 00004899 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2346 0000489C 81C3[88680000]      <1> 	add	ebx, wlist
  2347 000048A2 8A03                <1> 	mov	al, [ebx]
  2348 000048A4 20C0                <1> 	and	al, al
  2349 000048A6 7407                <1> 	jz	short sleep1
  2350 000048A8 53                  <1> 	push	ebx
  2351 000048A9 E82DFFFFFF          <1> 	call	putlu
  2352 000048AE 5B                  <1> 	pop	ebx
  2353                              <1> sleep1:
  2354 000048AF A0[B56D0000]        <1> 	mov	al, [u.uno]    
  2355 000048B4 8803                <1>   	mov	[ebx], al 	; put the process number
  2356                              <1> 				; in the wait channel
  2357                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2358                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2359                              <1> 				     ; / on the stack
  2360                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2361                              <1> 				     ; / to put to sleep in there
  2362                              <1> 	; 30/11/2021
  2363 000048B6 31DB                <1> 	xor	ebx, ebx
  2364 000048B8 8A1D[416D0000]      <1> 	mov	bl, [cdev]
  2365 000048BE 53                  <1> 	push	ebx
  2366                              <1>         ; 15/09/2015
  2367                              <1> 	;movzx	ebx, al
  2368 000048BF 88C3                <1> 	mov	bl, al
  2369 000048C1 C683[83690000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2370                              <1> 	; 27/02/2022 (p.waitc is not used)
  2371                              <1> 	;inc	ah
  2372                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2373                              <1> 	;
  2374                              <1> 	;
  2375                              <1> 	;push	word [cdev]
  2376                              <1> 	;	; mov cdev,-(sp) / nothing happened in isintr so
  2377 000048C8 E841FEFFFF          <1> 	call	swap
  2378                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2379                              <1>         ;pop	word [cdev]
  2380                              <1> 	;	; mov (sp)+,cdev / restore device
  2381                              <1> 	; 30/11/2021
  2382 000048CD 58                  <1> 	pop	eax
  2383 000048CE A2[416D0000]        <1> 	mov	[cdev], al
  2384 000048D3 E803000000          <1> 	call	isintr
  2385                              <1> 	; 22/09/2013
  2386                              <1> 	;jnz	sysret         
  2387                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2388                              <1>                		; br 2f / yes, return to new user
  2389                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2390                              <1> 				; / originally on the wait channel
  2391                              <1>        		; beq 1f / if 0 branch
  2392                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2393                              <1>        		; mov $300,*$ps / processor priority = 6
  2394                              <1> 		; jsr r0,putlu / create link to old process number
  2395                              <1>        		; clr *$ps / clear the status; process priority = 0
  2396                              <1> 	; 05/12/2021
  2397 000048D8 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2398                              <1>      ;1:
  2399 000048DA C3                  <1> 	retn
  2400                              <1> 		; rts r0 / return
  2401                              <1>      ;2:
  2402                              <1>         ;;jmp	sysret
  2403                              <1> 		; jmp sysret / return to user
  2404                              <1> 
  2405                              <1> isintr:
  2406                              <1> 	; 30/11/2021	
  2407                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	;
  2409                              <1> 	; 09/05/2013 - 30/05/2014
  2410                              <1> 	;
  2411                              <1> 	; Retro UNIX 8086 v1 modification !
  2412                              <1> 	; (Process/task switching and quit routine by using
  2413                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2414                              <1> 	;
  2415                              <1> 	; Retro UNIX 8086 v1 modification:
  2416                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2417                              <1> 	;  and there is a 'quit' request by user;
  2418                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2419                              <1> 	;  "nothing to do". (20/10/2013)
  2420                              <1> 	;
  2421                              <1> 	; 20/10/2013
  2422 000048DB 66833D[9A6D0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2423 000048E3 761F                <1> 	jna	short isintr2 ; retn
  2424                              <1> 	; 03/09/2013
  2425                              <1> 	; (nothing to do)
  2426                              <1> 	;retn
  2427                              <1> 	; 22/09/2013
  2428 000048E5 66833D[B06D0000]00  <1> 	cmp	word [u.intr], 0
  2429 000048ED 7615                <1> 	jna	short isintr2 ; retn
  2430                              <1> 	; 30/05/2014
  2431                              <1> 	;push	ax
  2432 000048EF 50                  <1> 	push	eax ; 30/11/2021 
  2433 000048F0 66A1[B26D0000]      <1> 	mov	ax, [u.quit]
  2434 000048F6 6609C0              <1> 	or	ax, ax ; 0 ?
  2435 000048F9 7408                <1> 	jz	short isintr1 ; zf = 1
  2436 000048FB 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2437 000048FF 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2438                              <1> 	;xor	ax, ax ; zf = 1
  2439                              <1> 	; 30/11/2021
  2440 00004901 31C0                <1> 	xor	eax, eax
  2441                              <1> isintr1:
  2442                              <1> 	;pop	ax
  2443                              <1> 	; 30/11/2021
  2444 00004903 58                  <1> 	pop	eax
  2445                              <1> isintr2: ; 22/09/2013
  2446                              <1> 	; zf=1 -> nothing to do
  2447 00004904 C3                  <1> 	retn
  2448                              <1> 
  2449                              <1> 	; UNIX v1 original 'isintr' routine... 
  2450                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2451                              <1>        	;mov     r2,-(sp) / save r2
  2452                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2453                              <1>         ;                 / typewriter
  2454                              <1>        	;beq     1f / if 0, do nothing except skip return
  2455                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2456                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2457                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2458                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2459                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2460                              <1>         ;              / of interrupts
  2461                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2462                              <1>      ;1:
  2463                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2464                              <1>      ;4:
  2465                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2466                              <1>        	;mov     (sp)+,r1
  2467                              <1>        	;rts     r0
  2468                              <1>      ;3: / interrupt char = quit (fs)
  2469                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2470                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2471                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2472                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2473                              <1>      ;1: / find process control tty entry in tty block
  2474                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2475                              <1>        	;beq     1f / block found go to 1f
  2476                              <1>        	;add     $8,r1 / look at next tty block
  2477                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2478                              <1>        	;blo     1b / no
  2479                              <1>        	;br      4b / no process control tty found so go to 4b
  2480                              <1>      ;1:
  2481                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2482                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2483                              <1>         ;                  / identifier
  2484                              <1>        	;inc     0f / increment
  2485                              <1>      ;1:
  2486                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2487                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2488                              <1>         ;             / being typed out after you hit the interrupt
  2489                              <1>         ;             / key
  2490                              <1>        	;br      1b
  2091                                  %include 'u5.s'      ; 03/06/2015
  2092                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2093                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2094                              <1> ; ****************************************************************************
  2095                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2096                              <1> ; Last Modification: 18/04/2022
  2097                              <1> ; ----------------------------------------------------------------------------
  2098                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2099                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2100                              <1> ;
  2101                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2102                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2103                              <1> ; <Bell Laboratories (17/3/1972)>
  2104                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2105                              <1> ;
  2106                              <1> ; Retro UNIX 8086 v1 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s
  2107                              <1> ;
  2108                              <1> ; ****************************************************************************
  2109                              <1> 
  2110                              <1> 	; 09/03/2022
  2111                              <1> 	; 09/01/2022
  2112                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2113                              <1> mget_w:
  2114                              <1> 	; 28/10/2021
  2115                              <1> 	; 22/08/2021
  2116                              <1> 	; 20/08/2021
  2117                              <1> 	; 25/05/2020
  2118                              <1> 	; 24/05/2020 - Retro UNIX 386 v2	
  2119 00004905 C605[FA6D0000]01    <1> 	mov	byte [mget_rw], 1 ; write access
  2120 0000490C EB07                <1> 	jmp	short mget
  2121                              <1> mget_r:
  2122                              <1> 	; 28/10/2021
  2123                              <1> 	; 22/08/2021
  2124                              <1> 	; 25/05/2020
  2125                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2126 0000490E C605[FA6D0000]00    <1> 	mov	byte [mget_rw], 0 ; read access	
  2127                              <1> mget:
  2128                              <1> 	; 09/03/2022
  2129                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2130                              <1> 	; 28/11/2021
  2131                              <1> 	; 22/11/2021
  2132                              <1> 	; 28/10/2021 - temporary (simplified code)
  2133                              <1> 	; 22/08/2021
  2134                              <1> 	; 20/08/2021
  2135                              <1> 	; 25/05/2020
  2136                              <1> 	; 24/05/2020
  2137                              <1> 	; 05/05/2020
  2138                              <1> 	; 02/05/2020, 03/05/2020
  2139                              <1> 	; 29/04/2020 - Retro UNIX 386 v2
  2140                              <1> 	; New inode model/format (Modified UNIX v7 inode model)
  2141                              <1> 	;	
  2142                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2143                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2144                              <1> 	;
  2145                              <1> 	; Get existing or (allocate) a new disk block for file
  2146                              <1> 	; 
  2147                              <1> 	; INPUTS ->
  2148                              <1> 	;    u.fofp (file offset pointer)
  2149                              <1> 	;    inode 
  2150                              <1> 	;    u.off (file offset)
  2151                              <1> 	; OUTPUTS ->
  2152                              <1> 	;    r1 (physical block number)
  2153                              <1> 	;    r2, r3, r5 (internal)
  2154                              <1> 	;
  2155                              <1> 	; ((AX = R1)) output
  2156                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2157                              <1> 	;
  2158                              <1> 	; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp
  2159                              <1> 
  2160                              <1> 	; Retro UNIX 386 v2 'mget' procedure
  2161                              <1> 	; source code reference:
  2162                              <1> 	; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan
  2163                              <1> 
  2164                              <1> 	; Get sector/block address for current file pointer
  2165                              <1> 	; (If file pointer points to a number greater than current file
  2166                              <1> 	; size, a new -empty- sector/block will be created/written.)
  2167                              <1> 
  2168                              <1> 	; Note: 'mget' procedure will be used for only RUNIX v2 FS.
  2169                              <1> 	;	(installable file system drivers will not use 'mget')
  2170                              <1> 	;	 !!! 512 bytes per sector !!!  ; 02/05/2020
  2171                              <1> 
  2172                              <1> 	; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit
  2173                              <1> 	; file offset for regular files and directories.
  2174                              <1> 	; ('mget' procedure will be called for regular files & directories)
  2175                              <1> 
  2176                              <1> 	; 28/10/2021
  2177                              <1> 	; Note: 'mget' uses only current inode ([ii], 'inode:')
  2178                              <1> 	; (inode must be loaded at 'inode:' addr by 'iget' before 'mget')  
  2179                              <1> 
  2180                              <1> 		; mov *u.fofp,mq / file offset in mq
  2181                              <1> 		; clr ac / later to be high sig
  2182                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2183                              <1> 		; mov mq,r2
  2184                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2185                              <1> 		; bne 4f / branch for large file
  2186                              <1> 
  2187                              <1> 	; 09/01/2022
  2188                              <1> 	; Return: eax = physical block/sector number
  2189                              <1> mget_0:	
  2190 00004915 8B35[786D0000]      <1>         mov     esi, [u.fofp]
  2191 0000491B 8B1E                <1> 	mov	ebx, [esi]
  2192                              <1>         ; ebx = file offset
  2193                              <1> 
  2194                              <1> 	; 20/08/2021
  2195 0000491D C1EB09              <1> 	shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2196                              <1> 
  2197 00004920 F605[E5680000]10    <1> 	test	byte [i.flgs+1], 10h ; is this a large or small file addr?
  2198 00004927 7405                <1> 	jz	short mget_1 ; small file addressing
  2199 00004929 E984000000          <1> 	jmp	mget_5	; large file addressing
  2200                              <1> mget_1:
  2201                              <1> 	; If large file flag is clear -not set- RUNIX v2 FS inode
  2202                              <1> 	; will contain 10 direct disk block/sector dword pointers.
  2203                              <1> 
  2204                              <1> 	; 05/05/2020
  2205                              <1> 	;shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2206                              <1> 
  2207 0000492E 83FB0A              <1> 	cmp	ebx, 10	; block 10
  2208 00004931 7338                <1> 	jnb	short mget_3 ; file offset >= 5120
  2209                              <1> 
  2210                              <1> 	; 05/05/2020
  2211                              <1> 	;cmp	ebx, 5120
  2212                              <1> 	;jnb	short mget_3 ; file offset >= 5120
  2213                              <1> 
  2214                              <1> 	;mov	bl, bh
  2215                              <1> 	;and	bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18
  2216                              <1> 	;	; max. value = 12h = 10010b = 18 (because ebx <= 5119) 
  2217                              <1> 	;shl	bl, 1	; * 2 ; max. value = 24h = 100100b = 36
  2218                              <1> 	;xor	bh, bh  ; clear bh
  2219                              <1> 		; RUNIX v2 (RUFS 2) file system bytes per sector value
  2220                              <1> 		; is always 512.
  2221                              <1> 		; ebx = 4*(ebx/512)  = 0 to 36
  2222                              <1> 
  2223                              <1> 	; 05/05/2020
  2224 00004933 C0E302              <1> 	shl	bl, 2 ; * 4
  2225                              <1> 		 ; ebx = 0 to 36
  2226                              <1> 
  2227 00004936 8B83[F0680000]      <1> 	mov	eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file
  2228                              <1> 	; 22/08/2021
  2229 0000493C 89DE                <1> 	mov	esi, ebx
  2230                              <1> 	;xor	ebx, ebx ; 0
  2231                              <1> 	; 09/03/2022
  2232                              <1> 	;; 09/01/2022
  2233                              <1> 	;xor	bl, bl
  2234                              <1> 
  2235 0000493E 09C0                <1> 	or	eax, eax
  2236 00004940 7512                <1> 	jnz	short mget_2 ; existing block/sector (logical)
  2237                              <1> 
  2238 00004942 56                  <1> 	push	esi ; * ; 22/08/2021
  2239 00004943 E875010000          <1> 	call	alloc_m ; 24/05/2020	
  2240                              <1> 	;call	alloc	; allocate a new sector/block for this file	
  2241                              <1> 			; eax = sector/block number
  2242                              <1> 			; ebx = buffer header address
  2243 00004948 5E                  <1> 	pop	esi ; * ; 22/08/2021
  2244                              <1> 	; 28/11/2021
  2245                              <1> 	;jc	short mget_2 
  2246                              <1> 			; cf = 1 -> eax = 'no free block' error
  2247                              <1> 	; 22/08/2021
  2248 00004949 8986[F0680000]      <1> 	mov	[esi+i.dskp], eax  ; logical sector/block address
  2249                              <1> 
  2250                              <1> 	; 09/01/2022
  2251 0000494F E8C2040000          <1> 	call	setimod	; set inode modification flag
  2252                              <1> 			; and set modification time
  2253                              <1> 
  2254                              <1> 	; eax = logical sector/block number
  2255                              <1> 	; ([idev] = logical drive number)
  2256                              <1> 	; 28/10/2021
  2257                              <1> 	; [cdev] = logical drive number (0 or 1)
  2258                              <1> 	;	(0 = root fs, 1 = mounted fs)
  2259                              <1> mget_2:
  2260                              <1> 	; 09/01/2022
  2261                              <1> 	; eax = logical sector/block number
  2262 00004954 F605[416D0000]01    <1> 	test	byte [cdev], 1
  2263 0000495B 7507                <1> 	jnz	short mget_14
  2264                              <1> 	; convert to physical sector/block number
  2265 0000495D 0305[186E0000]      <1> 	add	eax, [systm+SB.BootSectAddr]
  2266 00004963 C3                  <1> 	retn
  2267                              <1> 	; 09/01/2022
  2268                              <1> mget_14:
  2269                              <1> 	; convert to physical sector/block number
  2270 00004964 0305[20700000]      <1> 	add	eax, [mount+SB.BootSectAddr]
  2271 0000496A C3                  <1> 	retn
  2272                              <1> 	
  2273                              <1> 		; rts r0
  2274                              <1> mget_3: ; 3: / adding on block which changes small file to a large file
  2275                              <1> 	; 22/11/2021
  2276 0000496B E84D010000          <1> 	call	alloc_m ; 24/05/2020
  2277                              <1> 	;call	alloc	; allocate a new sector/block for this file
  2278                              <1> 			; eax = sector/block number
  2279                              <1> 			; ebx = buffer header  ; 24/05/2020
  2280                              <1> 	; 28/11/2021
  2281                              <1> 	;jc	short mget_2 ; error code in eax
  2282                              <1> 
  2283                              <1> 	; 09/01/2022
  2284                              <1> 	; convert to physical block/sector number
  2285 00004970 50                  <1> 	push	eax ; *!* ; logical sector/block number 
  2286 00004971 E8DEFFFFFF          <1> 	call	mget_2
  2287                              <1> 
  2288                              <1>         ; EAX (r1) = Physical block (sector) number
  2289 00004976 E877110000          <1> 	call 	wslot
  2290                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2291                              <1> 			     ; / first data word in buffer
  2292                              <1>         ; EAX (r1) = Physical block number
  2293                              <1> 	; 28/11/2021
  2294                              <1> 	; ebx = buffer (data) address
  2295                              <1> 	; 22/11/2021
  2296 0000497B 31C9                <1> 	xor	ecx, ecx
  2297 0000497D B10A                <1> 	mov 	cl, 10	; r3, transfer old physical block pointers
  2298                              <1> 			; into new indirect block area for the new
  2299                              <1> 			; large file		
  2300 0000497F 89DF                <1> 	mov 	edi, ebx ; r5
  2301 00004981 BE[F0680000]        <1> 	mov	esi, i.dskp  ; current inode's direct disk addr ptrs
  2302 00004986 89C2                <1> 	mov	edx, eax
  2303 00004988 31C0                <1> 	xor	eax, eax
  2304                              <1> mget_4:
  2305 0000498A A5                  <1> 	movsd 	
  2306 0000498B 8946FC              <1> 	mov	[esi-4], eax ; 0
  2307 0000498E E2FA                <1> 	loop	mget_4
  2308                              <1> 
  2309                              <1> 	; 22/11/2021
  2310 00004990 B176                <1> 	mov 	cl, 128-10 ; clear rest of data buffer
  2311                              <1> ;mget_4: ; 1
  2312 00004992 F3AB                <1> 	rep 	stosd
  2313                              <1> 		; clr (r5)+
  2314                              <1> 		; dec r3
  2315                              <1> 		; bgt 1b
  2316 00004994 89D0                <1> 	mov	eax, edx
  2317                              <1>         ; EAX (r1) = Physical block number
  2318 00004996 E864110000          <1> 	call	dskwr
  2319                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2320                              <1> 
  2321                              <1> 	;; EAX (r1) = Physical block number
  2322                              <1> 
  2323                              <1> 	; 09/01/2022        
  2324 0000499B 8F05[F0680000]      <1> 	pop	dword [i.dskp] ; *!* ; logical sector/block number
  2325                              <1>  
  2326                              <1> 	; eax = logical disk sector/block number/addr ; 09/01/2022
  2327                              <1> 	;mov 	[i.dskp], eax ; 22/11/2021 
  2328                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2329                              <1> 
  2330 000049A1 800D[E5680000]10    <1> 	or	byte [i.flgs+1], 10000b ; 10h ; 16  ; large file flag
  2331                              <1> 		; bis $10000,i.flgs / set large file bit 
  2332                              <1> 				  ; / in i.flgs word of i-node
  2333 000049A8 E869040000          <1> 	call	setimod
  2334                              <1> 		; jsr r0,setimod / set i-node modified flag
  2335                              <1> 
  2336 000049AD E963FFFFFF          <1> 	jmp	mget_0 ; 09/01/2022
  2337                              <1> 		; br mget
  2338                              <1> 
  2339                              <1> mget_5:  ; 4 ; large file
  2340                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2341                              <1> 	;
  2342                              <1> 	; Retro UNIX 386 v2 disk inode contains..
  2343                              <1> 	; (if large file flag is set)
  2344                              <1> 	; 8 indirect disk block/sector dword pointers
  2345                              <1> 	; +1 double indirect disk block/sector dword pointers
  2346                              <1> 	; +1 triple indirect disk block/sector dword pointers
  2347                              <1> 
  2348                              <1> 	; check indirect pointers limit (as file offset)
  2349                              <1> 	; 8*128 = 1024 blocks (or sectors) or 512 KB
  2350                              <1> 	; check dx (file offset hw) value
  2351                              <1> 	
  2352                              <1> 	; 03/05/2020
  2353                              <1> 	;cmp	ebx, 524288  ; is file offset >= 524288 ?
  2354                              <1> 	;jnb	short mget_6 ; yes, check double indirect limit
  2355                              <1> 
  2356                              <1> 	; 05/05/2020
  2357 000049B2 81FB00040000        <1> 	cmp	ebx, 1024    ; block 1024 (byte 524288)	
  2358 000049B8 7321                <1> 	jnb	short mget_6 ; check double indirect limit
  2359                              <1> 
  2360 000049BA C605[FC6D0000]01    <1> 	mov	byte [level], 1 ; levels, 1 = indirect blocks
  2361                              <1> 
  2362                              <1> 	; 05/05/2020
  2363                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2364                              <1> 
  2365 000049C1 88D9                <1> 	mov	cl, bl
  2366 000049C3 80E17F              <1> 	and	cl, 127
  2367 000049C6 880D[FD6D0000]      <1> 	mov	[level+1], cl ; level 1, direct block ptr index (0 to 127)
  2368 000049CC 66C1EB07            <1> 	shr	bx, 7 ; bl = level 0, indirect block pointer index (0 to 7)
  2369                              <1> 	;mov	[level+2], bl
  2370                              <1> 
  2371 000049D0 C0E302              <1> 	shl	bl, 2 ; * 4 to convert index number to offset
  2372                              <1> 
  2373                              <1> 	;mov	esi, i.dskp
  2374                              <1> 	;add	esi, ebx
  2375                              <1> 
  2376 000049D3 8DB3[F0680000]      <1> 	lea	esi, [ebx+i.dskp]
  2377                              <1> 
  2378 000049D9 EB66                <1> 	jmp	short mget_8
  2379                              <1> 
  2380                              <1> mget_6:
  2381                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2382                              <1> 	; 03/05/2020
  2383                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2384                              <1> 	; check double indirect pointer limit (as file offset)
  2385                              <1> 	; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB
  2386                              <1> 	; check dx (file offset hw) value
  2387                              <1> 	
  2388                              <1> 	;cmp	ebx, 8912896 ; >= 17408 sectors (16384+1024) ?	
  2389                              <1> 	;jnb	short mget_7 ; yes, use triple indirect pointer (block)
  2390                              <1> 
  2391                              <1> 	; 05/05/2020
  2392 000049DB 81FB00440000        <1> 	cmp	ebx, 17408   ; block 17408 (byte 8912896)	
  2393 000049E1 7329                <1> 	jnb	short mget_7 ; use triple indirect pointer (block)
  2394                              <1> 
  2395 000049E3 C605[FC6D0000]02    <1> 	mov	byte [level], 2  ; levels, 2 = double indirect blocks
  2396                              <1> 	
  2397                              <1> 	;sub	ebx, 524288 ; 1024 sectors
  2398                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2399                              <1> 			; (from sector 1024)
  2400                              <1> 	; 05/05/2020
  2401 000049EA 81EB00040000        <1> 	sub	ebx, 1024 ; offset from sector 1024
  2402                              <1> 	
  2403 000049F0 88D9                <1> 	mov	cl, bl
  2404 000049F2 80E17F              <1> 	and	cl, 127
  2405 000049F5 880D[FD6D0000]      <1> 	mov	[level+1], cl
  2406                              <1> 			; level 2, direct block ptr index (0 to 127)	
  2407 000049FB 66C1EB07            <1> 	shr	bx, 7
  2408 000049FF 881D[FE6D0000]      <1> 	mov	[level+2], bl
  2409                              <1> 			; level 1, indirect block ptr index (0 to 127)
  2410                              <1> 
  2411 00004A05 BE[10690000]        <1> 	mov	esi, i.dskp + 32 ; 8*4
  2412                              <1> 			; level 0, double indirect block pointer
  2413 00004A0A EB35                <1> 	jmp	short mget_8
  2414                              <1> 
  2415                              <1> mget_7:
  2416                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2417                              <1> 	; 03/05/2020
  2418                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2419                              <1> 	; triple indirect pointer ; 8912896 to 1082654720 bytes
  2420                              <1> 	;mov	esi, i.dskp + 36 ; 9*4
  2421                              <1> 
  2422 00004A0C C605[FC6D0000]03    <1> 	mov	byte [level], 3  ; levels, 3 = triple indirect blocks
  2423                              <1> 
  2424                              <1> 	;sub	ebx, 8912896 ; 17408 sectors (16384+1024)
  2425                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2426                              <1> 			; (from sector 17408)
  2427                              <1> 	; 05/05/2020
  2428 00004A13 81EB00440000        <1> 	sub	ebx, 17408 ; offset from sector 17408	
  2429                              <1> 
  2430 00004A19 88D9                <1> 	mov	cl, bl
  2431 00004A1B 80E17F              <1> 	and	cl, 127
  2432 00004A1E 880D[FD6D0000]      <1> 	mov	[level+1], cl  
  2433                              <1> 			; level 3, direct block ptr index (0 to 127)	
  2434 00004A24 C1EB07              <1> 	shr	ebx, 7	
  2435 00004A27 88D9                <1> 	mov	cl, bl
  2436 00004A29 80E17F              <1> 	and	cl, 127
  2437 00004A2C 880D[FE6D0000]      <1> 	mov	[level+2], cl
  2438                              <1> 			; level 2, indirect block ptr index (0 to 127)
  2439 00004A32 66C1EB07            <1> 	shr	bx, 7
  2440 00004A36 881D[FF6D0000]      <1> 	mov	[level+3], bl
  2441                              <1> 			; level 1, double indir blk ptr index (0 to 127)
  2442                              <1> 
  2443 00004A3C BE[14690000]        <1> 	mov	esi, i.dskp + 36 ; 9*4
  2444                              <1> 			; level 0, triple indirect block pointer
  2445                              <1> mget_8:
  2446                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2447 00004A41 8B06                <1> 	mov	eax, [esi]
  2448 00004A43 09C0                <1> 	or 	eax, eax ; R1
  2449 00004A45 751A                <1> 	jnz 	short mget_10 ; 2f
  2450                              <1> 		; bne 2f / if no indirect block exists
  2451 00004A47 56                  <1> 	push	esi	; * ; 24/05/2020
  2452                              <1> 
  2453 00004A48 E870000000          <1> 	call	alloc_m ; 24/05/2020
  2454                              <1> 	;call	alloc	; allocate a new block for this file	
  2455                              <1> 			; eax = block number
  2456                              <1> 			; ebx = buffer header address
  2457                              <1> 			; [pdn] = physical drive number ; 25/05/2020
  2458                              <1> 	;jc	mget_2	; cf -> 1 & eax = 0 -> no free block
  2459                              <1> 
  2460 00004A4D 5E                  <1> 	pop	esi	; * ; 24/05/2020
  2461                              <1> 	;jc	short mget_9
  2462                              <1> 
  2463                              <1> 	; 09/01/2022
  2464                              <1> 	; eax = logical sector/block number
  2465                              <1> 
  2466 00004A4E 8906                <1> 	mov	[esi], eax ; record sector/block address on i.dskp area
  2467                              <1> 
  2468 00004A50 E8C1030000          <1> 	call 	setimod
  2469                              <1> 		; jsr r0,setimod / set i-node modified byte
  2470                              <1> 	; EAX = new block number (logical)
  2471                              <1> 
  2472                              <1> 	; 09/01/2022
  2473                              <1> 	; convert to physical block/sector number
  2474 00004A55 E8FAFEFFFF          <1> 	call	mget_2
  2475                              <1> 	;
  2476 00004A5A E8ABFDFFFF          <1> 	call 	clear
  2477                              <1> 		; jsr r0,clear / clear new block
  2478                              <1> 	; 09/03/2022
  2479                              <1> 	;add	ebx, 8
  2480                              <1> 	; ebx = buffer data address
  2481                              <1> 	; 22/11/2021
  2482 00004A5F EB0A                <1> 	jmp	short mget_11
  2483                              <1> ;mget_9:
  2484                              <1> ;	pop	edx ; *  ; 09/01/2022
  2485                              <1> ;	retn
  2486                              <1> mget_10: ;2
  2487                              <1> 	; 09/01/2022
  2488                              <1> 	; eax = logical sector/block number/address
  2489                              <1> 	; convert to physical sector/block number/address
  2490 00004A61 E8EEFEFFFF          <1> 	call	mget_2	
  2491                              <1> 	; 05/03/2013
  2492                              <1> 	; EAX = r1, physical block number (of indirect block)
  2493 00004A66 E823100000          <1> 	call 	dskrd ; read indirect block
  2494                              <1> 		; jsr r0,dskrd / read in indirect block
  2495                              <1> 	;jc	short mget_9
  2496                              <1> mget_11:
  2497                              <1> 	; 22/11/2021
  2498                              <1> 	; eax = physical block/sector address
  2499                              <1> 	; ebx = buffer (data) address ; 09/03/2022
  2500                              <1> 
  2501 00004A6B 89C2                <1> 	mov	edx, eax ; *  ; save physical sector number in edx
  2502                              <1> 
  2503 00004A6D 0FB605[FC6D0000]    <1> 	movzx	eax, byte [level]
  2504 00004A74 8A80[FC6D0000]      <1> 	mov	al, [eax+level] ; get sector pointer offset
  2505 00004A7A C1E002              <1> 	shl	eax, 2 ; * 4 ; 09/01/2022
  2506                              <1> 	;shl	ax, 2 ; * 4
  2507                              <1> 
  2508 00004A7D 01C3                <1> 	add	ebx, eax
  2509                              <1> 
  2510 00004A7F 8B03                <1> 	mov 	eax, [ebx] ; put logical block no of block
  2511                              <1> 			   ; in file sought in R1 (EAX)
  2512                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2513                              <1> 	               	    ; / sought in r1
  2514                              <1> 
  2515 00004A81 21C0                <1> 	and	eax, eax  ; if logical sector/block number is zero
  2516                              <1> 			  ; then we need a new block for file
  2517 00004A83 740D                <1> 	jz	short mget_12
  2518                              <1> 
  2519 00004A85 FE0D[FC6D0000]      <1> 	dec	byte [level]
  2520 00004A8B 75D4                <1> 	jnz	short mget_10
  2521                              <1> 
  2522                              <1> 	; 09/03/2022
  2523                              <1> 	;sub	ebx, ebx ; ebx = 0 ; existing sector
  2524                              <1> 
  2525                              <1> 	;retn
  2526                              <1> 	; 09/01/2022
  2527                              <1> 	; eax = logical block/sector number
  2528 00004A8D E9C2FEFFFF          <1> 	jmp	mget_2
  2529                              <1> 
  2530                              <1> mget_12:
  2531                              <1> 	; 22/11/2021
  2532 00004A92 52                  <1> 	push	edx ; *
  2533 00004A93 53                  <1> 	push	ebx ; ** ; buffer data position
  2534 00004A94 E824000000          <1> 	call	alloc_m
  2535                              <1> 	;call	alloc	 ; allocate a new block for this file	
  2536                              <1> 			 ; eax = block number (logical)
  2537                              <1> 			 ; ebx = buffer header address
  2538 00004A99 5E                  <1> 	pop	esi ; **
  2539                              <1> 	; 09/01/2022
  2540                              <1> 	;pop	edx ; *
  2541                              <1> 	;jc	short mget_9 ; cf -> 1 & eax = 0 -> no free block
  2542                              <1> 
  2543 00004A9A 8906                <1> 	mov	[esi], eax ; record/save block number (logical)
  2544                              <1> 
  2545                              <1> 	; 22/11/2021
  2546 00004A9C 870424              <1> 	xchg	eax, [esp] ; *
  2547                              <1> 
  2548                              <1> 	; eax (r1) = physical block number (of indirect block)
  2549 00004A9F E84E100000          <1> 	call 	wslot
  2550                              <1> 		; jsr r0,wslot
  2551                              <1>         ; eax (r1) = physical block number
  2552                              <1> 	; ebx (r5) = pointer to buffer (indirect block)
  2553 00004AA4 E856100000          <1> 	call 	dskwr
  2554                              <1> 	; eax = r1 = physical block number (of indirect block)
  2555                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2556                              <1> 			     ; / back out on disk
  2557 00004AA9 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2558                              <1> 		; mov (sp),r1 / restore block number of new block	
  2559                              <1> 
  2560                              <1> 	; 09/01/2022
  2561                              <1> 	; eax = logical sector/block number/address of new block
  2562                              <1> 	; convert to physical sector/block number/address
  2563 00004AAA E8A5FEFFFF          <1> 	call	mget_2	
  2564                              <1> 
  2565 00004AAF E856FDFFFF          <1> 	call 	clear
  2566                              <1> 		; jsr r0,clear / clear new block
  2567                              <1> 
  2568 00004AB4 FE0D[FC6D0000]      <1> 	dec	byte [level]
  2569 00004ABA 75AF                <1> 	jnz	short mget_11 
  2570                              <1> 		; ebx = buffer (data) address ; 09/03/2022
  2571                              <1> 
  2572                              <1> 	; 09/01/2022
  2573                              <1> 	; eax = physical sector/block number/address of new block
  2574                              <1> 	
  2575                              <1> 	; 22/11/2021
  2576                              <1> 	; ebx = buffer address
  2577                              <1> mget_13: ; 2
  2578                              <1> 	; eax (r1) = Block number of new block
  2579 00004ABC C3                  <1> 	retn
  2580                              <1> 		; rts r0
  2581                              <1> 
  2582                              <1> 	; 09/01/2022
  2583                              <1> 	; 26/11/2021
  2584                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2585                              <1> alloc_m:
  2586                              <1> 	; 27/11/2021
  2587                              <1> 	; 28/10/2021
  2588                              <1> 	; 07/05/2021
  2589                              <1> 	; 26/05/2020
  2590                              <1> 	; 25/05/2020
  2591                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2592                              <1> 	; 'alloc' call in 'mget'
  2593                              <1> 	;
  2594                              <1> 	; (('mget_r' will be returned with error))
  2595                              <1> 	; (('mget_w' will continue to 'alloc'))
  2596                              <1> 
  2597                              <1> 	; Note: 'sysread' will return with cf = 0, eax = 0
  2598                              <1> 	; if [fofp] >= file size (eax = 0 --> EOF)
  2599                              <1> 	; So, if we are here, that means [fofp] < file size
  2600                              <1> 	;     but disk address is 0. 
  2601                              <1> 	
  2602 00004ABD 803D[FA6D0000]01    <1> 	cmp	byte [mget_rw], 1 ; write access ? (mget_w) 
  2603 00004AC4 730F                <1> 	jnb	short alloc ; yes (this is a call from 'mget_w')
  2604                              <1> 	; ((cf = 1))	
  2605                              <1> 	; no (this is a call from 'mget_r') !
  2606                              <1> 	;mov	eax, ERR_FILE_SIZE ; file size error (inode error!)
  2607                              <1> 		; [User may change this empty/invalid inode (disk) sector
  2608                              <1> 		; pointer with a new valid inode (disk) sector pointer 
  2609                              <1> 		; by writing new clear (zero) sector to same file position
  2610                              <1> 		; in order to correct file size -inode parm/content- error.
  2611                              <1> 		; It may be useful for recovering lost data if other sector
  2612                              <1> 		; pointers are not empty.]	
  2613                              <1> 	;retn
  2614                              <1> 	; 27/11/2021
  2615 00004AC6 C705[D86D0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE 
  2615 00004ACE 0000                <1>
  2616                              <1> 			; file size error (inode error!)
  2617 00004AD0 E998E7FFFF          <1> 	jmp	error
  2618                              <1> alloc:
  2619                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2620                              <1> 	; 27/11/2021
  2621                              <1> 	; 26/11/2021 - Major modification for Runix v2 file system
  2622                              <1> 	;	(I have called this kernel version as v1.2, it is a
  2623                              <1> 	;	 debug/test version just before Retro UNIX 386 v2 kernel)
  2624                              <1> 	;	((there were running problems on new version, 
  2625                              <1> 	;	  so i am developing an intermediate version with minimum
  2626                              <1> 	;	  modification on v1.1 code which is successfuly running))
  2627                              <1> 	;	 ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 
  2628                              <1> 	;	 
  2629                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2630                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2631                              <1> 	;
  2632                              <1> 	; get a free block and 
  2633                              <1> 	; set the corresponding bit in the free storage map
  2634                              <1> 	; 
  2635                              <1> 	; INPUTS ->
  2636                              <1> 	;    cdev (current device)
  2637                              <1> 	;    r2 
  2638                              <1> 	;    r3
  2639                              <1> 	; OUTPUTS ->
  2640                              <1> 	;    r1 (physical block number of block assigned)
  2641                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2642                              <1> 	;
  2643                              <1> 	; ((AX = R1)) output
  2644                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2645                              <1>         ;    ((Modified registers: edx, ecx)) 
  2646                              <1> 
  2647                              <1> 	; 26/11/2021
  2648                              <1> 	; INPUT:
  2649                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2650                              <1> 	; OUTPUT:
  2651                              <1> 	;	eax = disk block/sector number/address (physical)
  2652                              <1> 	;	(ebx = disk buffer address for sector/block in eax)
  2653                              <1> 	;
  2654                              <1> 	;    Note:	
  2655                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2656                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2657                              <1> 	;	modification flag will be set; but the superblock 
  2658                              <1> 	;	will not be written to it's disk in this 'alloc' procedure)
  2659                              <1> 	;
  2660                              <1> 	; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp
  2661                              <1> 
  2662                              <1> 	; 09/01/2022
  2663                              <1> 	; Return: eax = logical block/sector number 
  2664                              <1> 
  2665                              <1> 	; 26/11/2021
  2666 00004AD5 BB[146E0000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2667                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2668 00004ADA F605[416D0000]01    <1> 	test	byte [cdev], 1
  2669                              <1> 		; tst cdev
  2670 00004AE1 7405                <1> 	jz	short alloc_1
  2671                              <1> 		; beq 1f / drum is device
  2672 00004AE3 BB[1C700000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2673                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2674                              <1> 			      ; / free storage map
  2675                              <1> alloc_1: ; 1
  2676                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2677 00004AE8 F6436A01            <1> 	test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2678 00004AEC 7507                <1> 	jnz	short alloc_2  ; 'read only file system' error
  2679                              <1> 	;
  2680 00004AEE 8B4B38              <1> 	mov	ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors
  2681 00004AF1 21C9                <1> 	and	ecx, ecx
  2682 00004AF3 750F                <1> 	jnz	short alloc_3
  2683                              <1> alloc_2:
  2684                              <1> 	; 'no free blocks on disk !' error
  2685 00004AF5 C705[D86D0000]2100- <1> 	mov	dword [u.error], ERR_ALLOC
  2685 00004AFD 0000                <1>
  2686 00004AFF E969E7FFFF          <1> 	jmp	error
  2687                              <1> alloc_3:
  2688                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2689 00004B04 31C0                <1> 	xor	eax, eax
  2690                              <1> 	; 23/07/2021
  2691 00004B06 8B4B3C              <1> 	mov	ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number
  2692                              <1> 					 ; (as logical sector number)
  2693 00004B09 09C9                <1> 	or	ecx, ecx
  2694 00004B0B 7415                <1> 	jz	short alloc_5 ; 0 = initial/reset value or 'not valid'
  2695 00004B0D 41                  <1> 	inc	ecx ; 0FFFFFFFFh -> 0
  2696 00004B0E 7412                <1> 	jz	short alloc_5 ; 'not valid' or 'not calculated'
  2697 00004B10 49                  <1> 	dec	ecx ; restore first free block value
  2698 00004B11 89C8                <1> 	mov	eax, ecx
  2699                              <1> 	; 1 allocation byte (in fbm) is for 8 sectors
  2700 00004B13 C1E903              <1> 	shr	ecx, 3	; first free block number / 8
  2701 00004B16 80E1FC              <1> 	and	cl, ~3	; dword alignment (to backward)
  2702                              <1> 	; 27/11/2021
  2703 00004B19 890D[006E0000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2704                              <1> alloc_4:
  2705 00004B1F C1E80C              <1> 	shr	eax, 12 ; 1 fbm sector for 4096 sectors
  2706                              <1> alloc_5:
  2707                              <1> 	; 26/11/2021
  2708 00004B22 53                  <1> 	push	ebx ; ** ; superblock buffer address 
  2709                              <1> 	; eax = fbm sector index
  2710 00004B23 A3[046E0000]        <1> 	mov	[free_map_index], eax
  2711 00004B28 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2712                              <1> 			; free blocks map start sector addr
  2713                              <1> 	; 09/01/2022
  2714 00004B2B 034304              <1> 	add	eax, [ebx+SB.BootSectAddr] 
  2715                              <1> 			; + Hidden Sectors
  2716                              <1> 	;
  2717                              <1> 	; eax = physical sector number
  2718 00004B2E E85B0F0000          <1> 	call	dskrd
  2719                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2720                              <1> 	; eax = physical sector number
  2721                              <1> 	; ebx = buffer data address
  2722                              <1> 	; 27/11/2021
  2723 00004B33 8B15[006E0000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2724 00004B39 A3[086E0000]        <1> 	mov	[free_map_sector], eax ; physical sector number
  2725 00004B3E B9FF010000          <1> 	mov	ecx, 511
  2726                              <1> 	;and	edx, 511
  2727 00004B43 21CA                <1> 	and 	edx, ecx ; fbm byte offset in fbm buffer
  2728 00004B45 41                  <1> 	inc	ecx ; 512
  2729 00004B46 01D9                <1> 	add	ecx, ebx
  2730 00004B48 01DA                <1> 	add	edx, ebx ; + buffer address
  2731 00004B4A 5B                  <1> 	pop	ebx ; ** ; superblock buffer address 
  2732                              <1> 	;
  2733                              <1> 	; ebx = superblock buffer address
  2734                              <1> 	; edx = fbm buffer address + byte offset (dword aligned)
  2735                              <1> 	; ecx = fbm buffer address + 512
  2736                              <1> alloc_6:
  2737                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2738                              <1> 	;		for Retro UNIX 386 v1.2
  2739                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 code
  2740                              <1> 	; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors))
  2741                              <1> 	; ((Note: Logical drive size must be multiplies of 32 sectors))
  2742                              <1> 	; 19/05/2020
  2743                              <1> 	; edx = free blocks map byte address 
  2744 00004B4B 0FBC02              <1> 	bsf	eax, [edx] ; Scans source operand for first bit set (1).
  2745                              <1> 			  ; Clear ZF if a bit is found set (1) and 
  2746                              <1> 			  ; loads the destination with an index to
  2747                              <1> 			  ; first set bit. (0 -> 31) 
  2748                              <1> 			  ; Sets ZF to 1 if no bits are found set.
  2749 00004B4E 752A                <1> 	jnz	short alloc_8 ; ZF = 0 -> a free block has been found
  2750                              <1> 
  2751 00004B50 A1[006E0000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2752 00004B55 83C004              <1> 	add	eax, 4 ; next dword
  2753 00004B58 3B431C              <1> 	cmp	eax, [ebx+SB.FreeMapSize] ; fbm size in bytes
  2754 00004B5B 7209                <1> 	jb	short alloc_7
  2755                              <1> 	; invalidate superblock's first free block field
  2756 00004B5D C7433CFFFFFFFF      <1> 	mov	dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh
  2757                              <1> 	; 'no free blocks on disk !' error
  2758 00004B64 EB8F                <1> 	jmp	alloc_2
  2759                              <1> alloc_7:
  2760                              <1> 		; 26/05/2020
  2761                              <1> 		; NOTE: If ldrv size is not multiplies of 32 sectors,
  2762                              <1> 		; mod (ldrv size / 32) sectors (at the end of ldrv)
  2763                              <1> 		; can not be allocated (for regular files or dirs)! 
  2764                              <1> 		; (Kernel or runix fs installation program can use
  2765                              <1> 		;  this fact to save/duplicate critical sectors/data 
  2766                              <1> 		;  onto end sectors of that logical drive's runix fs.)
  2767                              <1> 
  2768                              <1> 	; 26/11/2021
  2769 00004B66 A3[006E0000]        <1> 	mov	[free_map_offset], eax
  2770                              <1> 	; 28/07/2021
  2771                              <1> 	; set next first free block value for search
  2772 00004B6B C1E003              <1> 	shl	eax, 3 ; * 8 ; first free block
  2773                              <1>  	; 26/11/2021
  2774 00004B6E 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2775                              <1> 	; search (scan) for next free block map dword (in buffer)
  2776 00004B71 83C204              <1> 	add	edx, 4 ; next dword
  2777 00004B74 39CA                <1> 	cmp	edx, ecx
  2778 00004B76 72D3                <1> 	jb	short alloc_6
  2779                              <1> 	; 27/11/2021
  2780 00004B78 EBA5                <1> 	jmp	short alloc_4
  2781                              <1> 
  2782                              <1> alloc_8:
  2783                              <1> 	; 26/11/2021
  2784                              <1> 	; convert bit index to xor value
  2785                              <1> 	; and then set allocated flag for corresponding fbm bit 
  2786 00004B7A 89C1                <1> 	mov	ecx, eax
  2787                              <1> 	;mov	cl, al 
  2788                              <1> 	;sub	eax, eax
  2789                              <1> 	;inc	al ; eax = 1
  2790 00004B7C B001                <1> 	mov	al, 1
  2791 00004B7E D3E0                <1> 	shl	eax, cl
  2792 00004B80 3102                <1> 	xor	[edx], eax  ; clear allocated block's bit in the fbm
  2793                              <1> 	; zero bit means allocated disk block (1 means free disk block) 
  2794                              <1> 
  2795 00004B82 A1[006E0000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2796                              <1> 		; note: eax is dword aligned (0,4,8,12..) !
  2797 00004B87 C1E003              <1> 	shl	eax, 3 ; * 8 ; free block number base
  2798 00004B8A 01C8                <1> 	add	eax, ecx ; add allocation bit index (0 to 31)	
  2799 00004B8C 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax ; current free block
  2800                              <1> 				; (which is being allocated here)
  2801                              <1> 
  2802                              <1> 	;mov	eax, [ebx+SB.FreeMapAddr] 
  2803                              <1> 	;		; free blocks map start sector addr
  2804                              <1> 	;add	eax, [free_map_index]
  2805                              <1> 	
  2806                              <1> 	;;add	eax, [ebx+SB.BootSectAddr] 
  2807                              <1> 	;		; + Hidden Sectors
  2808                              <1> 	; eax = physical sector number
  2809                              <1> 	
  2810                              <1> 	; 27/11/2021
  2811 00004B8F A1[086E0000]        <1> 	mov	eax, [free_map_sector] ; physical sector number
  2812                              <1> 	
  2813 00004B94 E8590F0000          <1> 	call	wslot
  2814                              <1> 	; ebx = buffer data address (write operation bit is set)
  2815                              <1> 	; eax = physical sector number
  2816                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2817                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2818                              <1> 
  2819                              <1> 	; 27/11/2021
  2820                              <1> 	;mov	[free_map_buffer], ebx ; save free map buffer address
  2821                              <1> 
  2822 00004B99 E8610F0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2823                              <1> 		      ; (at the beginning/head of the buffer chain)
  2824                              <1> 
  2825                              <1> 	; if we are here, buffer has been written to disk successfully 
  2826                              <1> 	; (otherwise cpu would jump to 'error' address)
  2827                              <1> 
  2828                              <1> 	; set superblock modified flag
  2829 00004B9E BA[566D0000]        <1> 	mov	edx, smod
  2830 00004BA3 BB[146E0000]        <1> 	mov	ebx, systm
  2831 00004BA8 F605[416D0000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2832 00004BAF 7406                <1> 	jz	short alloc_9  ; no, root device
  2833                              <1> 	; yes, mounted device
  2834 00004BB1 BB[1C700000]        <1> 	mov	ebx, mount
  2835                              <1> 	;mov	edx, mmod
  2836 00004BB6 42                  <1> 	inc	edx ; edx = offset mmod
  2837                              <1> alloc_9: 
  2838 00004BB7 FE02                <1> 	inc	byte [edx] ; superblock modified !
  2839                              <1> 	
  2840                              <1> 	; Allocating a new sector/block (for file) has been completed here.
  2841 00004BB9 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2842 00004BBC 40                  <1> 	inc	eax ; 0FFFFFFFFh -> 0 
  2843 00004BBD 7405                <1> 	jz	short alloc_10 ; not valid (not set)
  2844 00004BBF 48                  <1> 	dec	eax ; Free Blocks
  2845 00004BC0 48                  <1> 	dec	eax ; Free Blocks = Free Blocks - 1
  2846 00004BC1 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax
  2847                              <1> alloc_10:
  2848 00004BC4 E88C100000          <1> 	call	get_system_time
  2849                              <1> 		; eax = current time (as unix epoch time)
  2850                              <1> 	; 30/07/2021
  2851 00004BC9 89435C              <1> 	mov	[ebx+SB.ModifTime], eax
  2852                              <1> 
  2853 00004BCC 8B433C              <1> 	mov	eax, [ebx+SB.FirstFreeBlk] ; allocated block address
  2854 00004BCF FF433C              <1> 	inc	dword [ebx+SB.FirstFreeBlk] 
  2855                              <1> 				; +1, new value of first free block
  2856                              <1> 				; (new search will be started from here)
  2857                              <1> 				; ((it may not be free, no problem))
  2858                              <1> 
  2859                              <1> 	; put free map buffer address in ebx
  2860                              <1> 	; 27/11/2021
  2861                              <1> 	;mov	ebx, [free_map_buffer]
  2862                              <1> 
  2863 00004BD2 C3                  <1> 	retn	
  2864                              <1> 
  2865                              <1> 	; 11/02/2022
  2866                              <1> 	; 09/01/2022
  2867                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2868                              <1> free:
  2869                              <1> 	; 12/04/2022 (BugFix)
  2870                              <1> 	; 09/03/2022
  2871                              <1> 	; 11/02/2022
  2872                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2873                              <1> 	; 05/11/2021
  2874                              <1> 	; 29/10/2021 - temporary (simplified code)
  2875                              <1> 	; 14/08/2021
  2876                              <1> 	; 12/06/2021
  2877                              <1> 	; 07/06/2020
  2878                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  2879                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2880                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2881                              <1> 	;
  2882                              <1> 	; calculates byte address and bit position for given block number
  2883                              <1> 	; then sets the corresponding bit in the free storage map
  2884                              <1> 	; 
  2885                              <1> 	; INPUTS ->
  2886                              <1> 	;    r1 - block number for a block structured device
  2887                              <1> 	;    cdev - current device 
  2888                              <1> 	; OUTPUTS ->
  2889                              <1> 	;    free storage map is updated
  2890                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2891                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2892                              <1> 	;
  2893                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2894                              <1>         ;  ((Modified registers: DX, CX))  
  2895                              <1> 
  2896                              <1> 	; 27/11/2021
  2897                              <1> 	; INPUT:
  2898                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2899                              <1> 	;	eax = disk block/sector number/address (logical)
  2900                              <1> 	; OUTPUT:
  2901                              <1> 	;	ebx = superblock buffer address
  2902                              <1> 	;
  2903                              <1> 	;    Note:	
  2904                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2905                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2906                              <1> 	;	modification flag will be set; but the superblock 
  2907                              <1> 	;	will not be written to it's disk in this 'free' procedure)
  2908                              <1> 	;
  2909                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp 
  2910                              <1> 
  2911                              <1> 	; 27/11/2021
  2912 00004BD3 BB[146E0000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2913 00004BD8 F605[416D0000]01    <1> 	test	byte [cdev], 1
  2914 00004BDF 7405                <1> 	jz	short free_1
  2915 00004BE1 BB[1C700000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2916                              <1> free_1: ; 1
  2917                              <1> 	; 11/02/2022
  2918                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2919 00004BE6 F6436A01            <1> 	test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2920 00004BEA 740F                <1> 	jz	short free_2 
  2921                              <1> 	; 'read only file system' error
  2922 00004BEC C705[D86D0000]1E00- <1> 	mov	dword [u.error], ERR_READ_ONLY_FS
  2922 00004BF4 0000                <1>
  2923 00004BF6 E972E6FFFF          <1> 	jmp	error
  2924                              <1> free_2:
  2925 00004BFB 89C1                <1> 	mov	ecx, eax ; logical sector/block number
  2926 00004BFD A3[086E0000]        <1> 	mov	[free_map_sector], eax
  2927 00004C02 C1E903              <1> 	shr	ecx, 3	; convert to fbmap byte offset
  2928 00004C05 C1E80C              <1> 	shr	eax, 12 ; convert to fbmap sector index 
  2929                              <1> 			; (1 fb sector for 4096 sectors)
  2930                              <1> 	;and	cl, ~3	; dword alignment (to backward)
  2931                              <1> 	; 11/02/2022
  2932                              <1> 	;and	ecx, 511 ; convert to offset within fbm buffer
  2933 00004C08 81E1FC010000        <1> 	and	ecx, 1FCh ; 508, dword aligned offset (32 bit scan)
  2934                              <1> 	;
  2935 00004C0E 890D[006E0000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm buffer
  2936                              <1> 	; 27/11/2021
  2937                              <1> 	; eax = fbm sector index
  2938 00004C14 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2939                              <1> 			; free blocks map start sector address
  2940                              <1> 	; 09/01/2022
  2941 00004C17 034304              <1> 	add	eax, [ebx+SB.BootSectAddr]
  2942                              <1> 			; + Hidden Sectors
  2943                              <1> 	; 12/04/2022
  2944 00004C1A 53                  <1> 	push	ebx ; (*)
  2945                              <1> 	; ebx = superblock address
  2946                              <1> 	; eax = physical sector number
  2947 00004C1B E86E0E0000          <1> 	call	dskrd
  2948                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2949                              <1> 	; eax = physical sector number
  2950                              <1> 	; ebx = (fbm sector) buffer data address
  2951                              <1> 	; 27/11/2021
  2952 00004C20 A3[046E0000]        <1> 	mov	[free_map_index], eax  ; save physical sector address
  2953                              <1> 	; 12/04/2022
  2954 00004C25 8B15[006E0000]      <1> 	mov	edx, [free_map_offset] ; byte position in fbm buffer
  2955                              <1> 	; 11/02/2022
  2956                              <1> 	;(EDX contains -rounded down- dword aligned offset value)
  2957 00004C2B 01DA                <1> 	add	edx, ebx ; + (fbm sector) buffer start address
  2958                              <1> 	; 12/04/2022
  2959 00004C2D 5B                  <1> 	pop	ebx ; (*) superblock buffer address 	
  2960                              <1> 	;
  2961 00004C2E 29C0                <1> 	sub	eax, eax
  2962 00004C30 A0[086E0000]        <1> 	mov	al, [free_map_sector] ; logical sector number
  2963                              <1> 	;and	al, 7
  2964                              <1> 	; 11/02/2022
  2965 00004C35 241F                <1> 	and	al, 31 ; 32 bit fbm scan (with dword aligned offset)
  2966                              <1> 
  2967                              <1> 	; al = bit offset in fbm allocation byte
  2968                              <1> 	; edx = buffer address (start+offset)
  2969                              <1> 	; [free_map_offset] = byte position on fbm
  2970                              <1> 	; 27/11/2021
  2971 00004C37 0FAB02              <1> 	bts	[edx], eax  ; copy value of bit position in eax to cf
  2972                              <1> 			    ; then set same bit position at [edx]
  2973 00004C3A 7305                <1> 	jnc	short free_3 ; it was allocated sector
  2974                              <1> 
  2975                              <1> 	; already free sector !? 
  2976                              <1> 	; (nonsence or defective fs)
  2977                              <1> 
  2978 00004C3C 30C0                <1> 	xor	al, al ; 0  ; eax = 0
  2979 00004C3E 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2980                              <1> 	;mov	[ebx+SB.FreeBlocks], eax 
  2981                              <1> 		; invalidate free blocks count
  2982 00004C3F EB18                <1> 	jmp	short free_5
  2983                              <1> free_3:
  2984                              <1> 	; 27/11/2021
  2985 00004C41 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2986 00004C44 40                  <1> 	inc	eax
  2987                              <1> 	;jz	short free_4 ; 0FFFFFFFFh -> 0 (invalid!)
  2988                              <1> 	; 09/03/2022
  2989 00004C45 7501                <1> 	jnz	short free_4
  2990 00004C47 48                  <1> 	dec	eax  ; 0 -> 0FFFFFFFFh (invalid!)
  2991                              <1> free_4: 
  2992 00004C48 50                  <1> 	push	eax ; * ; number of free blocks 
  2993                              <1> 	;mov	eax, [free_map_index] ; fbm sector index
  2994                              <1> 	;add	eax, [ebx+SB.FreeMapAddr] 
  2995                              <1> 			; free blocks map start sector address
  2996                              <1> 	;add	eax, [ebx+SB.BootSectAddr]
  2997                              <1> 	;		; + Hidden Sectors
  2998 00004C49 A1[046E0000]        <1> 	mov	eax, [free_map_index] ; restore physical sector address
  2999                              <1> 	; eax = physical sector number
  3000 00004C4E E89F0E0000          <1> 	call	wslot
  3001                              <1> 	; ebx = buffer data address (write operation bit is set)
  3002                              <1> 	; eax = physical sector number
  3003                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  3004                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  3005                              <1> 
  3006 00004C53 E8A70E0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  3007                              <1> 		      ; (at the beginning/head of the buffer chain)
  3008                              <1> 
  3009                              <1> 	; if we are here, buffer has been written to disk successfully 
  3010                              <1> 	; (otherwise cpu would jump to 'error' address)
  3011 00004C58 58                  <1> 	pop	eax ; *  ; number of free blocks 
  3012                              <1> free_5:
  3013                              <1> 	; eax = number of free blocks 
  3014                              <1> 	;
  3015                              <1> 	; set superblock modified flag
  3016 00004C59 BA[566D0000]        <1> 	mov	edx, smod
  3017 00004C5E BB[146E0000]        <1> 	mov	ebx, systm
  3018 00004C63 F605[416D0000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  3019 00004C6A 7406                <1> 	jz	short free_6 ; no, root device
  3020                              <1> 	; yes, mounted device
  3021 00004C6C BB[1C700000]        <1> 	mov	ebx, mount
  3022                              <1> 	;mov	edx, mmod
  3023 00004C71 42                  <1> 	inc	edx ; edx = offset mmod
  3024                              <1> free_6: 
  3025 00004C72 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax 
  3026                              <1> 
  3027 00004C75 A1[086E0000]        <1> 	mov	eax, [free_map_sector] ; logical sector number
  3028 00004C7A 3B433C              <1> 	cmp	eax, [ebx+SB.FirstFreeBlk]
  3029 00004C7D 7303                <1> 	jnb	short free_7
  3030 00004C7F 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  3031                              <1> free_7:
  3032 00004C82 FE02                <1> 	inc	byte [edx] ; superblock modified !
  3033 00004C84 C3                  <1> 	retn
  3034                              <1> 	
  3035                              <1> iget:
  3036                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3037                              <1> 	; 30/11/2021
  3038                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3039                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3040                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  3041                              <1> 	;
  3042                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  3043                              <1> 	;
  3044                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  3045                              <1> 	; 
  3046                              <1> 	; INPUTS ->
  3047                              <1> 	;    ii - current i-number, rootdir
  3048                              <1> 	;    cdev - new i-node device
  3049                              <1> 	;    idev - current i-node device
  3050                              <1> 	;    imod - current i-node modified flag
  3051                              <1> 	;    mnti - cross device file i-number
  3052                              <1> 	;    r1 - i-numbe rof new i-node
  3053                              <1> 	;    mntd - mountable device number		
  3054                              <1> 	; 	 
  3055                              <1> 	; OUTPUTS ->
  3056                              <1> 	;    cdev, idev, imod, ii, r1
  3057                              <1> 	;
  3058                              <1> 	; ((AX = R1)) input/output
  3059                              <1> 	;
  3060                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3061                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3062                              <1> 
  3063                              <1> 	; 22/11/2021
  3064                              <1> 	;;mov	dl, [cdev] ; 18/07/2013
  3065                              <1> 	;;mov	dh, [idev] ; 07/08/2013
  3066                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3067                              <1> 	;mov	dh, [cdev]
  3068                              <1> 	;mov	dl, [idev]
  3069 00004C85 668B15[406D0000]    <1> 	mov	dx, [idev] ; [idev] in dl, [cdev] in dh
  3070                              <1> 	;
  3071                              <1> 	; 22/11/2021
  3072 00004C8C 25FFFF0000          <1> 	and	eax, 0FFFFh
  3073 00004C91 3B05[3C6D0000]      <1> 	cmp 	eax, [ii]
  3074                              <1> 		; cmp r1,ii / r1 = i-number of current file
  3075 00004C97 7504                <1> 	jne 	short iget_1
  3076                              <1> 		; bne 1f
  3077 00004C99 38F2                <1> 	cmp	dl, dh
  3078                              <1> 		; cmp idev,cdev
  3079                              <1> 			  ; / is device number of i-node = current device
  3080 00004C9B 746C                <1>         je	short iget_5
  3081                              <1> 	;	; beq 2f
  3082                              <1> 	; 14/08/2021
  3083                              <1> iget_1: ; 1:
  3084 00004C9D 30DB                <1> 	xor	bl, bl
  3085 00004C9F 381D[546D0000]      <1> 	cmp	[imod], bl ; 0	
  3086                              <1> 		; tstb imod / has i-node of current file
  3087                              <1> 			  ; / been modified i.e., imod set
  3088 00004CA5 7628                <1> 	jna	short iget_2
  3089                              <1> 		; beq 1f
  3090 00004CA7 881D[546D0000]      <1> 	mov	[imod], bl ; 0
  3091                              <1> 		; clrb imod / if it has, 
  3092                              <1> 			   ; / we must write the new i-node out on disk
  3093                              <1> 	; 22/11/2021 (32 bit push-pop)
  3094 00004CAD 50                  <1> 	push	eax ; *
  3095                              <1> 		; mov r1,-(sp)
  3096 00004CAE 52                  <1> 	push	edx ; **
  3097                              <1> 		; mov cdev,-(sp)
  3098 00004CAF A1[3C6D0000]        <1> 	mov	eax, [ii]
  3099                              <1> 		; mov ii,r1
  3100                              <1> 	;mov	dh, [idev]
  3101                              <1> 	;mov	[cdev], dh
  3102                              <1> 	; 09/01/2022
  3103 00004CB4 8815[416D0000]      <1> 	mov	[cdev], dl  ; dl = [idev]
  3104                              <1> 		; mov idev,cdev
  3105 00004CBA FEC3                <1> 	inc	bl ; 1
  3106                              <1> 	; 31/07/2013
  3107 00004CBC 881D[F86D0000]      <1> 	mov     [rw], bl ; 1 == write 
  3108                              <1> 	;;28/07/2013 rw -> u.rw
  3109                              <1>         ;;mov   [u.rw], bl ; 1 == write
  3110 00004CC2 E843000000          <1> 	call	icalc
  3111                              <1> 		; jsr r0,icalc; 1
  3112 00004CC7 5A                  <1> 	pop	edx ; **
  3113 00004CC8 8835[416D0000]      <1> 	mov	[cdev], dh ; 22/11/2021
  3114                              <1> 		; mov (sp)+,cdev
  3115 00004CCE 58                  <1> 	pop	eax ; *
  3116                              <1> 		; mov (sp)+,r1
  3117                              <1> iget_2: ; 1:
  3118                              <1> 	;and	ax, ax
  3119 00004CCF 21C0                <1> 	and	eax, eax ; 22/11/2021 (32 bit inode number)
  3120                              <1> 		; tst r1 / is new i-number non zero
  3121 00004CD1 7431                <1> 	jz	short iget_4 ; 2f
  3122                              <1> 		; beq 2f / branch if r1=0
  3123                              <1> 
  3124                              <1> 	;mov 	dh, [cdev]
  3125 00004CD3 08F6                <1> 	or	dh, dh ; 22/11/2021
  3126                              <1> 		; tst cdev / is the current device number non zero
  3127                              <1> 			 ; / (i.e., device =/ drum)
  3128 00004CD5 7515                <1> 	jnz	short iget_3 ;  1f
  3129                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  3130                              <1> 	; 22/11/2021
  3131 00004CD7 3B05[4A6D0000]      <1> 	cmp	eax, [mnti]
  3132                              <1> 	;cmp	ax, [mnti]			
  3133                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  3134                              <1> 			    ; / file (root directory of mounted device)
  3135 00004CDD 750D                <1> 	jne	short iget_3 ; 1f
  3136                              <1> 		; bne 1f
  3137                              <1>         ;mov    bl, [mntd]
  3138 00004CDF FEC6                <1> 	inc	dh ; mov dh, 1 ; 22/11/2021
  3139 00004CE1 8835[416D0000]      <1>         mov	[cdev], dh ; 22/11/2021
  3140                              <1> 		; mov mntd,cdev / make mounted device the current device
  3141                              <1> 	; 22/11/2021
  3142 00004CE7 A1[466D0000]        <1> 	mov	eax, [rootdir] ; rootdir = 1 (for runix v2 file system)
  3143                              <1> 	;mov	ax, [rootdir]
  3144                              <1> 		; mov rootdir,r1
  3145                              <1> iget_3: ; 1:
  3146                              <1> 	; 22/11/2021
  3147 00004CEC A3[3C6D0000]        <1> 	mov	[ii], eax ; 32 bit inode number
  3148                              <1> 	;mov	[ii], ax
  3149                              <1> 		; mov r1,ii
  3150                              <1> 	; 30/11/2021
  3151 00004CF1 8835[406D0000]      <1> 	mov	[idev], dh ; cdev 
  3152                              <1> 	;mov	[idev], dl ; cdev
  3153                              <1> 		; mov cdev,idev
  3154 00004CF7 30DB                <1> 	xor	bl, bl
  3155                              <1>         ; 31/07/2013
  3156 00004CF9 881D[F86D0000]      <1> 	mov     [rw], bl ; 0 == read 
  3157                              <1> 	;;28/07/2013 rw -> u.rw       
  3158                              <1>         ;;mov   [u.rw], bl ; 0 = read
  3159 00004CFF E806000000          <1> 	call	icalc
  3160                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  3161                              <1> iget_4: ; 2:
  3162                              <1> 	; 22/11/2021
  3163 00004D04 A1[3C6D0000]        <1> 	mov	eax, [ii]
  3164                              <1> 	;mov	ax, [ii]
  3165                              <1> 		; mov ii,r1
  3166                              <1> iget_5:
  3167 00004D09 C3                  <1> 	retn
  3168                              <1> 		; rts r0
  3169                              <1> 
  3170                              <1> icalc:
  3171                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3172                              <1> 	; 28/11/2021
  3173                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 
  3174                              <1> 	; 02/07/2015
  3175                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3176                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3177                              <1> 	;
  3178                              <1> 	; calculate physical block number from i-number then
  3179                              <1> 	; read or write that block
  3180                              <1> 	;
  3181                              <1> 	; 'icalc' is called from 'iget'
  3182                              <1> 	;
  3183                              <1> 	; for original unix v1:
  3184                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  3185                              <1>        	; / (i+31.) mod 16. bytes from its start
  3186                              <1> 	;
  3187                              <1> 	; for retro unix 8086 v1:
  3188                              <1> 	;  i-node is located in block (i+47)/16 and
  3189                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  3190                              <1> 	;
  3191                              <1> 	; INPUTS ->
  3192                              <1> 	;    r1 - i-number of i-node
  3193                              <1> 	; 	 
  3194                              <1> 	; OUTPUTS ->
  3195                              <1> 	;    inode r/w
  3196                              <1> 	;
  3197                              <1> 	; ((AX = R1)) input
  3198                              <1> 	;
  3199                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3200                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  3201                              <1> 	;
  3202                              <1> 
  3203                              <1> 	; 28/11/2021
  3204                              <1> 	;cmp	byte [idev], 0 ; [cdev] = [idev]
  3205 00004D0A 803D[416D0000]00    <1> 	cmp	byte [cdev], 0
  3206 00004D11 7607                <1> 	jna	short icalc_0r
  3207 00004D13 BD[1C700000]        <1> 	mov	ebp, mount  ; mounted file system's superblock 
  3208 00004D18 EB05                <1> 	jmp	short icalc_0m
  3209                              <1> icalc_0r:
  3210                              <1> 	; 28/11/2021
  3211 00004D1A BD[146E0000]        <1> 	mov	ebp, systm  ; root file system's superblock 
  3212                              <1> icalc_0m:
  3213                              <1> 	; 22/11/2021
  3214                              <1> 	;mov	edx, eax
  3215 00004D1F 8B15[3C6D0000]      <1> 	mov	edx, [ii] ; 32 bit inode number
  3216 00004D25 8B4528              <1> 	mov	eax, [ebp+SB.InodeTblAddr] ; inode table base address
  3217                              <1> 	;
  3218 00004D28 4A                  <1> 	dec	edx ; 0 based inode number 
  3219                              <1> 		    ; (inode index in inode table)
  3220 00004D29 52                  <1> 	push	edx ; *
  3221 00004D2A C1EA03              <1> 	shr	edx, 3
  3222 00004D2D 7402                <1> 	jz	short icalc_0t ; 0 for inodes 1 to 8
  3223 00004D2F 01D0                <1> 	add	eax, edx
  3224                              <1> icalc_0t:
  3225                              <1> 	; 09/01/2022
  3226                              <1> 	; eax = locical block/sector number 
  3227 00004D31 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  3228                              <1> 	; eax = physical block/sector number 
  3229 00004D34 E8550D0000          <1> 	call	dskrd
  3230                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  3231                              <1> 	; 31/07/2013
  3232 00004D39 803D[F86D0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  3233                              <1> 	;; 28/07/2013 rw -> u.rw
  3234                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  3235                              <1> 		; tst (r0)
  3236 00004D40 7605                <1> 	jna	short icalc_1
  3237                              <1> 		; beq 1f / branch to wslot when argument
  3238                              <1> 		       ; / in icalc call = 1
  3239                              <1> 	; eAX = r1 = block number
  3240 00004D42 E8AB0D0000          <1> 	call	wslot
  3241                              <1> 		; jsr r0,wslot / set up data buffer for write
  3242                              <1> 			     ; / (will be same buffer as dskrd got)
  3243                              <1> 	; EBX = r5 points to first word in data area for this block
  3244                              <1> icalc_1: ; 1:
  3245 00004D47 5A                  <1> 	pop	edx ; *
  3246                              <1> 	; 22/11/2021
  3247 00004D48 83E207              <1> 	and 	edx, 07h ; 8 inodes per inode table sector
  3248 00004D4B C1E206              <1> 	shl 	edx, 6 ; * 64 (inode size)
  3249                              <1> 	; edx = 64 * (mod(inodenumber-1)/8)
  3250 00004D4E 89DE                <1> 	mov	esi, ebx  ; ebx points to 1st word of the buffer
  3251 00004D50 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  3252                              <1>           	; eSI (r5) points to first word in i-node i.	
  3253                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  3254                              <1> 			     ; / 32.*(i+31.)mod16
  3255                              <1> 		; mov $5,lsh / for i-node i.
  3256                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  3257 00004D52 BF[E4680000]        <1> 	mov	edi, inode
  3258                              <1> 		; mov $inode,r1 / inode is address of first word 
  3259                              <1> 			      ; / of current i-node
  3260                              <1> 	;mov 	ecx, 8 ; 02/07/2015 (32 bit modification)
  3261                              <1> 	;	; mov $16.,r3
  3262                              <1> 	; 28/11/2021
  3263 00004D57 29C9                <1> 	sub	ecx, ecx
  3264 00004D59 B110                <1> 	mov	cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes
  3265                              <1> 	; 31/07/2013
  3266 00004D5B 382D[F86D0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3267                              <1>        ;;28/07/2013 rw -> u.rw                 
  3268                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3269                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  3270 00004D61 7609                <1> 	jna	short icalc_3
  3271                              <1> 		; beq 2f / r0 now contains proper return address 
  3272                              <1> 		       ; / for rts r0
  3273                              <1> icalc_2: ; 1:
  3274 00004D63 87F7                <1> 	xchg 	esi, edi
  3275                              <1> 	; overwrite old i-node (in buffer to be written)
  3276 00004D65 F3A5                <1> 	rep 	movsd
  3277                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  3278                              <1> 		; dec r3
  3279                              <1> 		; bgt 1b
  3280                              <1> 	;call	dskwr
  3281                              <1> 	;	; jsr r0,dskwr / write inode out on device
  3282                              <1> 	;retn
  3283                              <1> 	;	; rts r0
  3284                              <1> 	; 28/11/2021
  3285 00004D67 E9930D0000          <1> 	jmp	dskwr
  3286                              <1> icalc_3: ; 2:
  3287                              <1> 	; copy new i-node into inode area of (core) memory
  3288 00004D6C F3A5                <1> 	rep 	movsd
  3289                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  3290                              <1> 		                ; / "inode" area of core
  3291                              <1> 		; dec r3
  3292                              <1> 		; bgt 2b
  3293 00004D6E C3                  <1> 	retn
  3294                              <1> 		; rts r0
  3295                              <1> 
  3296                              <1> access:
  3297                              <1> 	; 13/03/2022
  3298                              <1> 	; 25/12/2021
  3299                              <1> 	; 19/12/2021
  3300                              <1> 	; 28/11/2021
  3301                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3302                              <1> 	; 31/10/2021 - temporary (simplified code)
  3303                              <1> 	; 14/06/2021
  3304                              <1> 	; 02/05/2021
  3305                              <1> 	; 27/03/2021
  3306                              <1> 	; 26/03/2021
  3307                              <1> 	; 25/03/2021
  3308                              <1> 	; 23/03/2021 (Retro UNIX 386 v2 - Beginning)
  3309                              <1> 	;	((ref: unix v7 source - fio.c))
  3310                              <1> 	; ref: INODE STRUCTURE of Retro UNIX v2 file system
  3311                              <1> 	;	07/02/2020, 'RETRO UNIX v2 Inodes.pdf'
  3312                              <1> 	;	 
  3313                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3314                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3315                              <1> 	;
  3316                              <1> 	; check whether user is owner of file or user has read or write
  3317                              <1> 	; permission (based on i.flgs).
  3318                              <1> 	;
  3319                              <1> 	; INPUTS ->
  3320                              <1> 	;    r1 - i-number of file
  3321                              <1> 	;    u.uid
  3322                              <1> 	; arg0 -> (owner flag mask)	 		
  3323                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  3324                              <1> 	; OUTPUTS ->
  3325                              <1> 	;    inode (or jump to error)
  3326                              <1> 	;
  3327                              <1> 	; ((AX = R1)) input/output
  3328                              <1> 	;
  3329                              <1> 	;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))
  3330                              <1> 
  3331                              <1> 	; 26/03/2021
  3332                              <1> 	; INPUT:
  3333                              <1> 	;	eax = inode number (ax)
  3334                              <1> 	;	 dx = mode (IEXEC, IREAD or IWRITE) 
  3335                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3336                              <1> 	;	
  3337                              <1> 	; OUTPUT:
  3338                              <1> 	;	inode (or jump to error)
  3339                              <1> 	;	eax (ax) = [ii] = inode number
  3340                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3341                              <1> 	;
  3342                              <1> 	; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp
  3343                              <1> 	;
  3344                              <1> 	; IREAD	 equ 100h ; read permission flag, owner
  3345                              <1> 	; IWRITE equ 80h  ; write permission flag, owner
  3346                              <1> 	; IEXEC	 equ 40h  ; execute permission flag, owner	 
  3347                              <1> 		
  3348                              <1> 	; 23/03/2021
  3349 00004D6F 52                  <1> 	push	edx ; save flag (DX)
  3350                              <1> 	;push	dx  ; save flag (DL)
  3351 00004D70 E810FFFFFF          <1> 	call	iget
  3352                              <1> 		; jsr r0,iget / read in i-node for current directory
  3353                              <1> 			    ; / (i-number passed in r1)
  3354                              <1> 	;;mov	cl, [i.flgs]
  3355                              <1> 	;;	; mov i.flgs,r2
  3356                              <1> 	; 23/03/2021
  3357                              <1> 	;mov	cx, [i.iflgs]	
  3358                              <1> 
  3359                              <1> 	;;pop	dx  ; restore flag (DL)
  3360                              <1> 	; 23/03/2021
  3361 00004D75 5A                  <1> 	pop	edx ; restore flag (DX)
  3362                              <1> 
  3363                              <1> 	; 28/11/2021 (iget will not return here if there is an error)
  3364                              <1> 	; 31/10/2021
  3365                              <1> 	;jc	short access_5
  3366                              <1> 
  3367                              <1> 	; 31/10/2021
  3368                              <1> 	; Note: If eax input is same with [mnti], 'iget' will change
  3369                              <1> 	; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 
  3370                              <1> 
  3371                              <1> 	; 27/03/2021
  3372                              <1> 	; 23/03/2021
  3373                              <1> 	; (check if it is write permission flag)
  3374 00004D76 6681FA8000          <1> 	cmp	dx, 80h ; IWRITE
  3375 00004D7B 775E                <1> 	ja	short access_r	; IREAD = 100h (owner)
  3376 00004D7D 722B                <1> 	jb	short access_x	; IEXEC = 40h (owner)
  3377                              <1> 	; IWRITE (80h)
  3378                              <1> access_w:
  3379                              <1> 	; 23/03/2021
  3380                              <1> 	; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure))
  3381                              <1> 	;mov	bl, [idev]
  3382                              <1> 	;call	getfs
  3383                              <1>  	;movzx	ebx, byte [idev]  ; logical drive number
  3384                              <1> 	;shl	bx, 6 ; * 64	  ; of current inode	
  3385                              <1> 	;add	ebx, ldrvtable	
  3386                              <1> 	;;test	byte [ebx+ldrv.pflags], 01h ; read only fs flag
  3387                              <1> 	;;jz	short access_0
  3388                              <1> 	;; 14/06/2021
  3389                              <1> 	; 14/06/2021
  3390                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3391                              <1> 	;mov	edi, [ebx+ldrv.superblk]
  3392                              <1> 	;test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3393                              <1> 	;jz	short access_0
  3394                              <1> 	; 31/10/2021
  3395 00004D7F 803D[416D0000]01    <1> 	cmp	byte [cdev], 1
  3396 00004D86 7207                <1> 	jb	short access_7 ; [cdev] = 0
  3397                              <1> 	; [cdev] = 1
  3398                              <1> 	; 28/11/2021
  3399 00004D88 BF[1C700000]        <1> 	mov	edi, mount ; mounted file system's superblock buffer
  3400 00004D8D EB05                <1> 	jmp	short access_8
  3401                              <1> access_7:
  3402                              <1> 	; 28/11/2021
  3403 00004D8F BF[146E0000]        <1> 	mov	edi, systm ; root file system's superblock buffer
  3404                              <1> access_8:
  3405 00004D94 F6476A01            <1> 	test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3406 00004D98 7441                <1> 	jz	short access_0
  3407                              <1> 
  3408                              <1> 	; 23/03/2021
  3409                              <1> 	;mov	dword [u.error], ERR_READ_ONLY_FS
  3410                              <1> 	;		; 'read only file system !' error
  3411                              <1> 	;jmp	error
  3412                              <1> 
  3413                              <1> 	; 19/12/2021
  3414 00004D9A F605[E5680000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  3415 00004DA1 7438                <1> 	jz	short access_0  ; no, device file
  3416                              <1> 
  3417                              <1> 	; 31/10/2021
  3418 00004DA3 B81E000000          <1> 	mov	eax, ERR_READ_ONLY_FS
  3419                              <1> 			; 'read only file system !' error
  3420                              <1> 	; 27/03/2021
  3421 00004DA8 EB27                <1> 	jmp	short access_5
  3422                              <1> 
  3423                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3424                              <1> 
  3425                              <1> 	;mov	dh, [u.uid]
  3426                              <1> 	;cmp	dh, [i.uid]
  3427                              <1> 	;	; cmpb i.uid,u.uid / is user same as owner of file
  3428                              <1> 	;jne	short access_1
  3429                              <1> 		; bne 1f / no, then branch
  3430                              <1> access_x:
  3431                              <1> 	; IEXEC (40h)
  3432                              <1> 	; 27/03/2021
  3433 00004DAA 668B1D[E4680000]    <1> 	mov	bx, [i.flgs]
  3434 00004DB1 F6C780              <1> 	test	bh, 80h ; regular file ?
  3435 00004DB4 7416                <1> 	jz	short access_4 ; not executable file !
  3436 00004DB6 F6C740              <1> 	test	bh, 40h	; directory ?
  3437 00004DB9 7511                <1> 	jnz	short access_4 ; not executable file !
  3438 00004DBB 668B0D[B66D0000]    <1> 	mov	cx, [u.uid]
  3439 00004DC2 6609C9              <1> 	or	cx, cx
  3440 00004DC5 7520                <1> 	jnz	short access_3 ; (restricted user)
  3441                              <1> 	; (super user)
  3442                              <1> 	;test	[i.flgs], dl ; execute permission for owner
  3443                              <1> 	;test	byte [i.flgs], 49h ; for owner, group, others
  3444 00004DC7 F6C349              <1> 	test	bl, 49h ; exec perm for owner, group, others
  3445 00004DCA 7549                <1> 	jnz	short access_2
  3446                              <1> access_4:
  3447                              <1> 	; 31/10/2021
  3448 00004DCC B816000000          <1> 	mov	eax, ERR_NOT_EXECUTABLE
  3449                              <1> 			; 'not executable file !' error
  3450                              <1> 	; 26/03/2021
  3451                              <1> ;;sysexec_not_exf:
  3452                              <1> ;	mov	dword [u.error], ERR_NOT_EXECUTABLE
  3453                              <1> ;			; 'not executable file !' error
  3454                              <1> ;access_5:
  3455                              <1> ;	jmp	error
  3456                              <1> 	
  3457                              <1> 	; 31/10/2021
  3458                              <1> access_5:
  3459 00004DD1 A3[D86D0000]        <1> 	mov	[u.error], eax
  3460 00004DD6 E992E4FFFF          <1> 	jmp	error
  3461                              <1> 
  3462                              <1> access_r:
  3463                              <1> 	; 27/03/2021
  3464                              <1> access_0:
  3465                              <1> 	; 23/03/2021
  3466 00004DDB 668B0D[B66D0000]    <1> 	mov	cx, [u.uid]
  3467 00004DE2 6609C9              <1> 	or	cx, cx ; 0 ; root ?
  3468                              <1> 	;jz	short access_2 ; yes
  3469                              <1> 	; 25/12/2021
  3470 00004DE5 741E                <1> 	jz	short access_1 ; yes
  3471                              <1> access_3:
  3472                              <1> 	; 13/03/2022
  3473 00004DE7 663B0D[E8680000]    <1> 	cmp	cx, [i.uid] ; owner ?
  3474 00004DEE 7415                <1> 	je	short access_1 ; yes
  3475                              <1> 	;; owner ?
  3476 00004DF0 8A1D[EA680000]      <1> 	mov	bl, [i.gid]
  3477                              <1> 	;cmp	cx, [i.uid]
  3478                              <1> 	;;je	short access_1
  3479                              <1> 	;; 02/05/2021
  3480                              <1> 	;jne	short access_6
  3481                              <1> 	; 13/03/2022
  3482                              <1> 	; same group ?
  3483 00004DF6 66C1EA03            <1> 	shr	dx, 3
  3484                              <1> 	; check owner's group number/ID
  3485 00004DFA 3A1D[BA6D0000]      <1> 	cmp	bl, [u.gid] ; same group number/ID ?
  3486 00004E00 7403                <1> 	je	short access_1 ; yes
  3487                              <1> 	; one of others
  3488                              <1> 	;shr	dx, 6
  3489                              <1> 	;jmp	short access_1 ; others
  3490                              <1> 	; 13/03/2022
  3491                              <1> 	; one of others
  3492 00004E02 C0EA03              <1> 	shr	dl, 3
  3493                              <1> ;	; 13/03/2022
  3494                              <1> ;	jmp	short access_1 ; others
  3495                              <1> ;access_6:
  3496                              <1> ;	;shr	cl, 2
  3497                              <1> ;	;	; asrb r2 / shift owner read write bits into non owner
  3498                              <1> ;	;	;       ; / read/write bits
  3499                              <1> ;	;	; asrb r2
  3500                              <1> ;
  3501                              <1> ;	; 23/03/2021
  3502                              <1> ;	; same group ?
  3503                              <1> ;	shr	dx, 3
  3504                              <1> ;	;mov	cl, [u.gid]
  3505                              <1> ;	;cmp	cl, [i.gid]
  3506                              <1> ;	;je	short access_1
  3507                              <1> ;	; 02/05/2021
  3508                              <1> ;	cmp	bl, [u.gid]
  3509                              <1> ;	je	short access_1 ; same group, different owner
  3510                              <1> ;
  3511                              <1> ;	; others
  3512                              <1> ;	;shr	dx, 3
  3513                              <1> ;	shr	dl, 3
  3514                              <1> ;	;jmp	short access_1	
  3515                              <1> ;
  3516                              <1> ;;access_1: ; 1:
  3517                              <1> ;	;and	cl, dl
  3518                              <1> ;	;	; bit r2,(r0)+ / test read-write flags against argument
  3519                              <1> ;	;		     ; / in access call
  3520                              <1> ;	;jnz	short access_2
  3521                              <1> ;	;	; bne 1f
  3522                              <1> ;	
  3523                              <1> ;	;or	dh, dh	; super user (root) ?
  3524                              <1> ;	;	; tstb u.uid
  3525                              <1> ;	;jz	short access_2 ; yes, super user
  3526                              <1> ;	;;jnz	error
  3527                              <1> ;	;	; beq 1f
  3528                              <1> ;	;	; jmp error
  3529                              <1> ;	
  3530                              <1> ;	;mov	dword [u.error], ERR_FILE_ACCESS 
  3531                              <1> ;	;		; 'permission denied !' error
  3532                              <1> ;	;jmp	error
  3533                              <1> 
  3534                              <1> access_1:
  3535                              <1> 	; 23/03/2021
  3536 00004E05 668515[E4680000]    <1> 	test	dx, [i.flgs]
  3537 00004E0C 7507                <1> 	jnz	short access_2
  3538                              <1> 
  3539                              <1> 	;; r/w permission error
  3540                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3541                              <1> 	;		; 'permission denied !' error
  3542                              <1> 	;;jmp	error
  3543                              <1> 
  3544                              <1> 	; 31/10/2021
  3545 00004E0E B80B000000          <1> 	mov	eax, ERR_FILE_ACCESS 
  3546                              <1> 			; 'permission denied !' error
  3547                              <1> 	; 27/03/2021
  3548 00004E13 EBBC                <1> 	jmp	short access_5
  3549                              <1> 
  3550                              <1> access_2: ; 1:
  3551                              <1> 	;; DL = flags
  3552                              <1> 	;retn
  3553                              <1> 	;	; rts r0
  3554                              <1> 	; 27/03/2021
  3555                              <1> 	; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h)
  3556 00004E15 C3                  <1> 	retn
  3557                              <1> 
  3558                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  3559                              <1> %if 0
  3560                              <1> 
  3561                              <1> setimod:
  3562                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3563                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3564                              <1> 	;
  3565                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3566                              <1> 	; the inode has been modified. Also puts the time of modification
  3567                              <1> 	; into the inode.
  3568                              <1> 	;
  3569                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3570                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3571                              <1> 	;
  3572                              <1> 	
  3573                              <1> 	;push 	edx
  3574                              <1> 	push	eax
  3575                              <1> 
  3576                              <1> 	mov 	byte [imod], 1
  3577                              <1> 		; movb $1,imod / set current i-node modified bytes
  3578                              <1> 	; Erdogan Tan 14-7-2012
  3579                              <1> 	call 	epoch
  3580                              <1> 		 ; mov s.time,i.mtim 
  3581                              <1> 			    ; / put present time into file modified time
  3582                              <1> 		 ; mov s.time+2,i.mtim+2
  3583                              <1> 
  3584                              <1> 	mov 	[i.mtim], eax
  3585                              <1> 	
  3586                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3587                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3588                              <1> 	cmp	dword [i.ctim], 0
  3589                              <1> 	jnz	short setimod_ok
  3590                              <1> 
  3591                              <1> 	mov 	[i.ctim], eax
  3592                              <1> 
  3593                              <1> setimod_ok: ; 31/07/2013
  3594                              <1> 	pop	eax
  3595                              <1> 	;pop	edx
  3596                              <1> 	
  3597                              <1> 	retn
  3598                              <1> 		; rts r0
  3599                              <1> %endif
  3600                              <1> 
  3601                              <1> setimod:
  3602                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  3603                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3604                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3605                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3606                              <1> 	;
  3607                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3608                              <1> 	; the inode has been modified. Also puts the time of modification
  3609                              <1> 	; into the inode.
  3610                              <1> 	;
  3611                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3612                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3613                              <1> 	;
  3614                              <1> 
  3615                              <1> 	; Reference:
  3616                              <1> 	; 25/01/2020 - 'UNIXHDCP.ASM', 'setimod' procedure
  3617                              <1> 	;	(Retro UNIX 386 v2 file system installation utility)
  3618                              <1> 
  3619                              <1> 	; 25/05/2020
  3620                              <1> 	;
  3621                              <1> 	; INPUT:
  3622                              <1> 	;	none
  3623                              <1> 	; OUTPUT:
  3624                              <1> 	;	inode times and [imod] will be set
  3625                              <1> 	;	      ([imodx] will be reset)
  3626                              <1> 	;	cf = 0 	
  3627                              <1> 
  3628                              <1> 	; Modified registers: ecx, (edx)?
  3629                              <1> 	
  3630                              <1> 	;push 	edx
  3631 00004E16 50                  <1> 	push	eax
  3632                              <1> 
  3633 00004E17 C605[546D0000]01    <1> 	mov 	byte [imod], 1
  3634                              <1> 		; movb $1,imod / set current i-node modified bytes
  3635                              <1> 
  3636                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3637 00004E1E A1[20690000]        <1> 	mov	eax, [i.ctim] ; inode (file) creation time
  3638 00004E23 21C0                <1> 	and	eax, eax
  3639 00004E25 7518                <1> 	jnz	short setimod_4
  3640                              <1> 
  3641                              <1> 	; New file
  3642                              <1> setimod_1:
  3643                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  3644                              <1> 	;	 (Modified UNIX v7 inode and new FS construction) 	
  3645                              <1> 	;
  3646 00004E27 E8290E0000          <1> 	call	get_system_time ; get current (unix epoch) time
  3647                              <1> 
  3648                              <1> 	;; Erdogan Tan 14-7-2012
  3649                              <1> 	;call 	epoch
  3650                              <1> 	;	 ; mov s.time,i.mtim 
  3651                              <1> 	;		    ; / put present time into file modified time
  3652                              <1> 	;	 ; mov s.time+2,i.mtim+2
  3653                              <1> 	;
  3654                              <1> 	;mov 	[i.mtim], eax
  3655                              <1> 
  3656                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3657                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3658                              <1> 	;cmp	dword [i.ctim], 0
  3659                              <1> 	;jnz	short setimod_ok
  3660                              <1> 		
  3661 00004E2C A3[20690000]        <1> 	mov 	[i.ctim], eax
  3662                              <1> 	
  3663                              <1> 	; 25/05/2020
  3664 00004E31 EB05                <1> 	jmp	short setimod_3
  3665                              <1> 
  3666                              <1> setimod_2:
  3667                              <1> 	; File/Directory data (file size or content) is changed
  3668                              <1> 	; This is last modification date&time
  3669 00004E33 A3[1C690000]        <1> 	mov	[i.mtim], eax
  3670                              <1> setimod_3:
  3671                              <1> 	; 19/09/2019 ('UNIXHDCP.ASM', 'setimod' by Erdogan Tan)
  3672                              <1> 	; This is last access or last changing date&time
  3673                              <1> 	; of inode (chmod,chown,chgrp,link)
  3674                              <1> 	; parameters (without file/dir data changing)
  3675 00004E38 A3[18690000]        <1> 	mov	[i.atim], eax
  3676                              <1> 
  3677                              <1> setimod_ok: ; 31/07/2013
  3678 00004E3D 58                  <1> 	pop	eax
  3679                              <1> 	;pop	edx
  3680                              <1> 	
  3681 00004E3E C3                  <1> 	retn
  3682                              <1> 		; rts r0
  3683                              <1> setimod_4:
  3684                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3685 00004E3F 31C9                <1> 	xor	ecx, ecx
  3686 00004E41 390D[1C690000]      <1> 	cmp	[i.mtim], ecx ; 0
  3687 00004E47 76EA                <1> 	jna	short setimod_2
  3688                              <1> 
  3689 00004E49 E8070E0000          <1> 	call	get_system_time ; get current (unix epoch) time
  3690                              <1> 	; ((system time will be updated directly by timer interrupt))
  3691                              <1> 
  3692 00004E4E 803D[556D0000]00    <1> 	cmp	byte [imodx], 0 ; flag means "file/dir data is same but
  3693 00004E55 76DC                <1> 	jna	short setimod_2 ; inode has been changed"
  3694                              <1> 
  3695                              <1> 	; File/Dir data (File size or content) is same but
  3696                              <1> 	; inode's mode, link count, owner or group id has been changed
  3697                              <1> 	; (so, we do not change last modification date&time)
  3698 00004E57 C605[556D0000]00    <1> 	mov	byte [imodx], 0 ; reset inode modified (extended) flag
  3699 00004E5E EBD8                <1> 	jmp	short setimod_3
  3700                              <1> 
  3701                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3702                              <1> %if 0
  3703                              <1> 	; Retro UNIX 386 v1.1 'itrunc' code
  3704                              <1> itrunc:
  3705                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3706                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  3707                              <1> 	;
  3708                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3709                              <1> 	;  to zero length.
  3710                              <1> 	;
  3711                              <1> 	; INPUTS ->
  3712                              <1> 	;    r1 - i-number of i-node
  3713                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  3714                              <1> 	;    i.flgs - large file flag		
  3715                              <1> 	;    i.size - size of file	
  3716                              <1> 	; 	 
  3717                              <1> 	; OUTPUTS ->
  3718                              <1> 	;    i.flgs - large file flag is cleared
  3719                              <1> 	;    i.size - set to 0	
  3720                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  3721                              <1> 	;    setimod - set to indicate i-node has been modified
  3722                              <1> 	;    r1 - i-number of i-node  					
  3723                              <1> 	;
  3724                              <1> 	; ((AX = R1)) input/output
  3725                              <1> 	;
  3726                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  3727                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3728                              <1> 
  3729                              <1> 	call	iget
  3730                              <1> 		; jsr r0,iget
  3731                              <1> 	mov	esi, i.dskp
  3732                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  3733                              <1> 	xor	eax, eax
  3734                              <1> itrunc_1: ; 1:
  3735                              <1> 	lodsw
  3736                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  3737                              <1> 	or 	ax, ax
  3738                              <1> 	jz	short itrunc_5
  3739                              <1> 		; beq 5f
  3740                              <1> 	push	esi
  3741                              <1> 		; mov r2,-(sp)
  3742                              <1> 	test    word [i.flgs], 1000h    
  3743                              <1> 		; bit $10000,i.flgs / test large file bit?
  3744                              <1> 	jz	short itrunc_4
  3745                              <1> 		; beq 4f / if clear, branch
  3746                              <1> 	push	eax
  3747                              <1> 		; mov r1,-(sp) / save block number of indirect block
  3748                              <1> 	call	dskrd
  3749                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  3750                              <1> 			     ; / pointed to by r5
  3751                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  3752                              <1> 	mov	ecx, 256
  3753                              <1> 		; mov $256.,r3 / move word count into r3
  3754                              <1> 	mov	esi, ebx
  3755                              <1> itrunc_2: ; 2:
  3756                              <1> 	lodsw
  3757                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  3758                              <1> 			     ; / physical block number
  3759                              <1> 	and	ax, ax
  3760                              <1> 	jz	short itrunc_3
  3761                              <1> 		; beq 3f / branch if zero
  3762                              <1> 	;push	ecx
  3763                              <1> 	push	cx
  3764                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3765                              <1> 	;push	esi
  3766                              <1> 		; mov r5,-(sp)
  3767                              <1> 	call	free
  3768                              <1> 		; jsr r0,free / free block in free storage map
  3769                              <1> 	;pop	esi
  3770                              <1> 		; mov(sp)+,r5
  3771                              <1> 	pop	cx
  3772                              <1> 	;pop	ecx
  3773                              <1> 		; mov (sp)+,r3
  3774                              <1> itrunc_3: ; 3:
  3775                              <1> 	loop	itrunc_2
  3776                              <1> 		; dec r3 / decrement word count
  3777                              <1> 		; bgt 2b / branch if positive
  3778                              <1> 	pop	eax
  3779                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3780                              <1> 			     ; / indirect block
  3781                              <1> 	; 01/08/2013
  3782                              <1>         and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3783                              <1> itrunc_4: ; 4:
  3784                              <1> 	call	free
  3785                              <1> 		; jsr r0,free / free indirect block
  3786                              <1> 	pop	esi
  3787                              <1> 		; mov (sp)+,r2
  3788                              <1> itrunc_5: ; 5:
  3789                              <1> 	cmp	esi, i.dskp+16
  3790                              <1> 		; cmp r2,$i.dskp+16.
  3791                              <1> 	jb	short itrunc_1	
  3792                              <1> 		; bne 1b / branch until all i.dskp entries check
  3793                              <1> 	; 01/08/2013
  3794                              <1> 	;and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3795                              <1> 		; bic $10000,i.flgs / clear large file bit
  3796                              <1> 	mov	edi, i.dskp
  3797                              <1> 	mov	cx, 8
  3798                              <1> 	xor 	ax, ax
  3799                              <1> 	mov	[i.size], ax ; 0
  3800                              <1> 		; clr i.size / zero file size
  3801                              <1> 	rep	stosw
  3802                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3803                              <1> 			   ; / zero block pointers
  3804                              <1> 	call	setimod
  3805                              <1> 		; jsr r0,setimod / set i-node modified flag
  3806                              <1> 	mov	ax, [ii]
  3807                              <1> 		; mov ii,r1
  3808                              <1> 	retn
  3809                              <1> 		; rts r0
  3810                              <1> 
  3811                              <1> 	; Retro UNIX 386 v1.1 'imap' code
  3812                              <1> imap:
  3813                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3814                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3815                              <1> 	;
  3816                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3817                              <1> 	; allocation bit for an i-node whose number in r1.
  3818                              <1> 	;
  3819                              <1> 	; INPUTS ->
  3820                              <1> 	;    r1 - contains an i-number
  3821                              <1> 	;    fsp - start of table containing open files
  3822                              <1> 	;
  3823                              <1> 	; OUTPUTS ->
  3824                              <1> 	;    r2 - byte address of byte with the allocation bit
  3825                              <1> 	;    mq - a mask to locate the bit position.	
  3826                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3827                              <1> 	;
  3828                              <1> 	; ((AX = R1)) input/output
  3829                              <1> 	; ((DL/DX = MQ)) output
  3830                              <1> 	; ((BX = R2)) output
  3831                              <1> 	;
  3832                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3833                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3834                              <1> 	;
  3835                              <1> 		; / get the byte that has the allocation bit for 
  3836                              <1> 		; / the i-number contained in r1
  3837                              <1> 	;mov	dx, 1
  3838                              <1> 	mov	dl, 1
  3839                              <1> 		; mov $1,mq / put 1 in the mq
  3840                              <1> 	movzx	ebx, ax
  3841                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3842                              <1>  		          ; / in the map we must find
  3843                              <1> 	sub	bx, 41
  3844                              <1> 		; sub $41.,r2 / r2 has i-41
  3845                              <1> 	mov	cl, bl
  3846                              <1> 		; mov r2,r3 / r3 has i-41
  3847                              <1> 	and	cl, 7
  3848                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3849                              <1> 			   ; / the bit position
  3850                              <1> 	jz	short imap1
  3851                              <1> 	;shl	dx, cl
  3852                              <1> 	shl	dl, cl
  3853                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3854                              <1> imap1:			   ; / to the left to mask the correct bit
  3855                              <1> 	shr	bx, 3
  3856                              <1> 		; asr r2
  3857                              <1> 		; asr r2
  3858                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3859                              <1> 		       ; / from the start of the map
  3860                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3861                              <1> 	mov	esi, systm
  3862                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3863                              <1> 				; / the super block for drum
  3864                              <1> 	;cmp	word [cdev], 0
  3865                              <1> 	cmp	byte [cdev], 0
  3866                              <1> 		; tst cdev / is the device the disk
  3867                              <1> 	jna	short imap2
  3868                              <1> 		; beq 1f / yes
  3869                              <1> 	add	esi, mount - systm
  3870                              <1> 		; add $mount-systm,r2 / for mounted device,
  3871                              <1> 			; / r2 points to 1st word of its super block
  3872                              <1> imap2: ; 1:
  3873                              <1> 	add	bx, [esi] ;; add free map size to si
  3874                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3875                              <1> 	add	bx, 4
  3876                              <1> 	add	ebx, esi
  3877                              <1>         	; add (sp)+,r2 / ?
  3878                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3879                              <1> 		      ;; (2 + free map size + 2)
  3880                              <1> 		; add $2,r2 / ?
  3881                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3882                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3883                              <1> 	retn
  3884                              <1> 		; rts r0
  3885                              <1> %endif
  3886                              <1> 
  3887                              <1> 	; Retro UNIX 386 v2.0 'itrunc' code
  3888                              <1> itrunc:
  3889                              <1> 	; 26/03/2022
  3890                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  3891                              <1> 	; 07/06/2020
  3892                              <1> 	; 02/06/2020
  3893                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3894                              <1> 	;
  3895                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3896                              <1> 	;  to zero length.
  3897                              <1> 	; 07/06/2020
  3898                              <1> 	; 02/06/2020
  3899                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3900                              <1> 	;
  3901                              <1> 	; 'itrunc' truncates a file whose i-number is given
  3902                              <1> 	; in ax to zero length.
  3903                              <1> 	;
  3904                              <1> 
  3905                              <1> 	; Reference: 
  3906                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  3907                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'itrunc' procedure
  3908                              <1> 
  3909                              <1> 	; * Free all the disk blocks associated
  3910                              <1> 	; * with the specified inode structure.
  3911                              <1> 	
  3912                              <1> 	; INPUT: 
  3913                              <1> 	;	(e)ax = inode number
  3914                              <1> 	; OUTPUT: 
  3915                              <1> 	;	inode will be modified (file size = 0)
  3916                              <1> 	;	; 26/03/20221
  3917                              <1> 	;	eax = 0 (if cf=0)
  3918                              <1> 
  3919                              <1> 	; (Modified registers: eax, edx, ecx, ebx, esi, edi, ebp) 
  3920                              <1> 
  3921                              <1> 	; 07/06/2020
  3922                              <1> 
  3923                              <1> 	; [cdev] = current logical drive number
  3924                              <1> 	;    eax = inode number (for [cdev])
  3925                              <1> 
  3926 00004E60 E820FEFFFF          <1> 	call 	iget
  3927                              <1> 	; 10/01/2022
  3928                              <1> 	;jc	short itrunc_0 ; error code in eax (al)
  3929                              <1> 
  3930                              <1> 	;    eax = inode number, [ii]
  3931                              <1> 	; [cdev] = current logical drive number (same with input)
  3932                              <1> 	; [idev] = logical drive number of current inode, [ii]
  3933                              <1> 	;   [ii] = current inode ([ii] = ax input, if ax was not zero)
  3934                              <1> 	; [imod] = 0		
  3935                              <1> 	; ([imodx] = 0)
  3936                              <1> 
  3937 00004E65 F605[E5680000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file or directory	
  3938 00004E6C 750F                <1> 	jnz	short itrunc_1
  3939                              <1> 
  3940                              <1> 	; 10/01/2022
  3941 00004E6E C705[D86D0000]FF00- <1> 	mov	dword [u.error], ERR_NOT_REGULAR ; 255 
  3941 00004E76 0000                <1>
  3942                              <1> 			; 'not a regular file (or directory) !' error
  3943                              <1> itrunc_0:
  3944 00004E78 E9F0E3FFFF          <1> 	jmp	error
  3945                              <1> itrunc_1:
  3946 00004E7D F605[E5680000]10    <1> 	test	byte [i.flgs+1], 10h ; large file (indirect blocks)
  3947 00004E84 7528                <1> 	jnz	short itrunc_5 ; large file
  3948 00004E86 BE[F0680000]        <1> 	mov	esi, i.dskp ; disk address pointer 0
  3949                              <1> itrunc_2:
  3950 00004E8B AD                  <1> 	lodsd
  3951 00004E8C 21C0                <1> 	and	eax, eax
  3952 00004E8E 740C                <1> 	jz	short itrunc_3 ; empty ! (no more sectors/blocks)
  3953                              <1> 	; eax = block address to be released
  3954 00004E90 56                  <1> 	push	esi ; * ; 10/01/2022
  3955 00004E91 E83DFDFFFF          <1> 	call	free
  3956                              <1> 	; modified registers: ebx, ecx, edx, esi, edi, ebp 
  3957                              <1> 	; 10/01/2022
  3958                              <1> 	;jc	short itrunc_0 ; error code in eax
  3959 00004E96 5E                  <1> 	pop	esi ; * ; 10/01/2022
  3960 00004E97 31C0                <1> 	xor	eax, eax ; 0
  3961 00004E99 8946FC              <1> 	mov	[esi-4], eax ; 0
  3962                              <1> itrunc_3:
  3963 00004E9C 81FE[18690000]      <1> 	cmp	esi, i.dskp+40
  3964 00004EA2 72E7                <1> 	jb	short itrunc_2 ; next disk address ptr
  3965                              <1> itrunc_4:
  3966 00004EA4 A3[EC680000]        <1> 	mov	[i.size], eax ; 0
  3967                              <1> 	;mov	[i.size_h], al ; 0
  3968                              <1> 	
  3969                              <1> 	; clear large file flag
  3970                              <1> 	;and     byte [i.flgs+1], 0EFh ; 11101111b ; not 10h
  3971                              <1> 		
  3972                              <1> 	;call	setimod
  3973                              <1> 	;retn
  3974 00004EA9 E968FFFFFF          <1> 	jmp	setimod
  3975                              <1> 
  3976                              <1> itrunc_5:
  3977                              <1> 	; free disk blocks by using triple indirect blocks at first
  3978 00004EAE BE[14690000]        <1> 	mov	esi, i.dskp+36
  3979 00004EB3 8B06                <1> 	mov	eax, [esi]
  3980 00004EB5 09C0                <1> 	or	eax, eax
  3981 00004EB7 740C                <1> 	jz	short itrunc_6
  3982                              <1> 
  3983 00004EB9 BA02000000          <1> 	mov	edx, 2 ; Triple indirect sign (level = 2)
  3984 00004EBE E835000000          <1> 	call	tloop
  3985                              <1> 	; 10/01/2022
  3986                              <1> 	;jc	short itrunc_0
  3987                              <1> 		; eax = 0	
  3988 00004EC3 8906                <1> 	mov	[esi], eax ; 0
  3989                              <1> itrunc_6:
  3990                              <1> 	; free disk blocks by using double indirect blocks at second
  3991 00004EC5 BE[10690000]        <1> 	mov	esi, i.dskp+32
  3992 00004ECA 8B06                <1> 	mov	eax, [esi]
  3993 00004ECC 21C0                <1> 	and	eax, eax 
  3994 00004ECE 740C                <1> 	jz	short itrunc_7
  3995                              <1> 
  3996 00004ED0 BA01000000          <1> 	mov	edx, 1 ; Double indirect sign (level = 1)
  3997 00004ED5 E81E000000          <1> 	call	tloop
  3998                              <1> 	; 10/01/2022
  3999                              <1> 	;jc	short itrunc_0
  4000                              <1> 		; eax = 0	
  4001 00004EDA 8906                <1> 	mov	[esi], eax ; 0
  4002                              <1> 	;esi = i.dskp+32
  4003                              <1> itrunc_7:
  4004                              <1> 	; free disk blocks by using single indirect blocks at third
  4005 00004EDC 83EE04              <1> 	sub	esi, 4
  4006 00004EDF 8B06                <1> 	mov	eax, [esi]
  4007 00004EE1 09C0                <1> 	or	eax, eax
  4008 00004EE3 7409                <1> 	jz	short itrunc_8
  4009                              <1> 
  4010 00004EE5 29D2                <1> 	sub	edx, edx ; 0  ; Single indirect sign (level = 0)
  4011 00004EE7 E80C000000          <1> 	call	tloop
  4012                              <1> 	; 10/01/2022
  4013                              <1> 	;jc	short itrunc_0
  4014                              <1> 		; eax = 0
  4015 00004EEC 8906                <1> 	mov	[esi], eax ; 0
  4016                              <1> itrunc_8:
  4017 00004EEE 81FE[F0680000]      <1> 	cmp	esi, i.dskp
  4018 00004EF4 77E6                <1> 	ja	short itrunc_7
  4019 00004EF6 EBAC                <1> 	jmp	short itrunc_4
  4020                              <1> 
  4021                              <1> tloop:
  4022                              <1> 	; 26/03/2022
  4023                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  4024                              <1> 	; 07/06/2020
  4025                              <1> 	; 03/06/2020
  4026                              <1> 	; 02/06/2020
  4027                              <1> 	; 26/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  4028                              <1> 	; 
  4029                              <1> 	; * Free all the disk blocks associated
  4030                              <1> 	; * with the specified inode structure.
  4031                              <1> 
  4032                              <1> 	; Reference: 
  4033                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  4034                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'tloop' procedure
  4035                              <1> 
  4036                              <1> 	; INPUT: 
  4037                              <1> 	;	03/06/2020
  4038                              <1> 	;	eax = indirect block number/address (logical)
  4039                              <1> 	;	edx = level (in dl) 
  4040                              <1> 	;	(0 = indirect, 1 = double indr. 2 = triple indr.) 	
  4041                              <1> 	;
  4042                              <1> 	; OUTPUT: 
  4043                              <1> 	;	indirect blocks will be released
  4044                              <1> 	;
  4045                              <1> 	; Modified registers: eax, ebx, ecx, edx
  4046                              <1> 
  4047                              <1> 	; 03/06/2020
  4048                              <1> 
  4049 00004EF8 57                  <1> 	push	edi ; *
  4050 00004EF9 56                  <1> 	push	esi ; **
  4051                              <1> 
  4052 00004EFA 50                  <1> 	push	eax ; ***
  4053                              <1> 
  4054 00004EFB 52                  <1> 	push	edx ; **** level
  4055                              <1> 
  4056                              <1> 	; [ii] = current inode number
  4057                              <1> 	;;[idev] = logical drive number of current inode, [ii]
  4058                              <1> 	; eax = logical sector/block number
  4059                              <1> 
  4060                              <1> 	; 26/03/2022
  4061                              <1> 	; [cdev] = logical drive number (0 or 1)
  4062                              <1> 
  4063                              <1> 	; 10/01/2022
  4064                              <1> 	; convert to physical sector/block number/address
  4065 00004EFC E853FAFFFF          <1> 	call	mget_2	
  4066                              <1> 
  4067 00004F01 E8880B0000          <1> 	call	dskrd ; read disk sector
  4068                              <1> 
  4069                              <1> 		;; ebx = buffer header address
  4070                              <1> 		;; eax = physical sector/block number 
  4071                              <1> 		;; [pdn] = phsysical drive (index) number
  4072                              <1> 		
  4073                              <1> 		;; Modified registers: eax, edx, ecx, esi, edi
  4074                              <1> 		;; If cf = 1 --> eax = error code (al)
  4075                              <1> 
  4076                              <1> 	; 10/01/2022
  4077                              <1> 	; Return from 'dskrd': (Retro UNIX 386 v1.2)
  4078                              <1> 	; 	eax = physical block/sector number
  4079                              <1> 	; 	ebx = buffer data address
  4080                              <1>  	; Modified registers: edx, ecx, ebx, esi, edi, ebp
  4081                              <1>  
  4082 00004F06 5A                  <1> 	pop	edx ; **** ; level in dl
  4083                              <1> 	; 10/01/2022
  4084                              <1> 	;jc	short tloop_5
  4085                              <1> 
  4086                              <1> 	;mov	esi, [ebx+bufhdr.address] ; buffer address
  4087                              <1> 	; 10/01/2022
  4088 00004F07 89DE                <1> 	mov	esi, ebx ; buffer data address	
  4089                              <1> 
  4090                              <1> 	; 07/06/2020
  4091 00004F09 B980000000          <1> 	mov	ecx, 512/4 ; 128 dwords	
  4092                              <1> 
  4093 00004F0E 80FA01              <1> 	cmp	dl, 1 ; -
  4094 00004F11 722C                <1> 	jb	short tloop_7
  4095 00004F13 7407                <1> 	je	short tloop_1
  4096 00004F15 BF[24760000]        <1> 	mov	edi, trpi_buf ; triple indirect buffer address
  4097 00004F1A EB05                <1> 	jmp	short tloop_2
  4098                              <1> tloop_1:
  4099 00004F1C BF[24740000]        <1> 	mov	edi, dbli_buf ; double indirect buffer address
  4100                              <1> tloop_2:
  4101                              <1> 	; copy disk r/w buffer content to indirect block buffer
  4102                              <1> 	;mov	ecx, 512/4 ; 128 dwords	
  4103 00004F21 F3A5                <1> 	rep	movsd
  4104                              <1> 
  4105 00004F23 FECA                <1> 	dec	dl ; -
  4106                              <1> 		   ; next indirect block level, 2 -> 1, 1 -> 0
  4107 00004F25 89FE                <1> 	mov	esi, edi  ; (dbli, trpi) indirect buffer + 512
  4108 00004F27 B180                <1> 	mov	cl, 128 ; 128 dwords
  4109                              <1> tloop_3:
  4110 00004F29 83EE04              <1> 	sub	esi, 4  ; previous pointer
  4111                              <1> 
  4112 00004F2C 8B06                <1> 	mov	eax, [esi]
  4113                              <1> 
  4114 00004F2E 09C0                <1> 	or	eax, eax ; 0
  4115 00004F30 7409                <1> 	jz	short tloop_4
  4116                              <1> 
  4117                              <1> 	; 26/03/2022
  4118 00004F32 52                  <1> 	push	edx ; @@
  4119                              <1> 	; 03/06/2020
  4120 00004F33 51                  <1> 	push	ecx ; @
  4121 00004F34 E8BFFFFFFF          <1> 	call	tloop
  4122 00004F39 59                  <1> 	pop	ecx ; @
  4123                              <1> 	; 26/03/2022
  4124 00004F3A 5A                  <1> 	pop	edx ; @@
  4125                              <1> 	; 10/01/2022
  4126                              <1> 	;jc	short tloop_5
  4127                              <1> tloop_4:
  4128 00004F3B E2EC                <1> 	loop	tloop_3
  4129                              <1> 
  4130 00004F3D EB1A                <1> 	jmp	short tloop_10
  4131                              <1> 
  4132                              <1> 	; 10/01/2022
  4133                              <1> ;tloop_5:
  4134                              <1> ;	pop	edx ; ***  ; discard eax
  4135                              <1> ;	; error code in eax
  4136                              <1> ;tloop_6:
  4137                              <1> ;	pop	esi ; **
  4138                              <1> ;	pop	edi ; *
  4139                              <1> ;	retn
  4140                              <1> 	
  4141                              <1> 	; free blocks in current indirect block
  4142                              <1> tloop_7:
  4143                              <1> 	;mov	ecx, 512/4  ; 128 dwords
  4144 00004F3F 81C6FC010000        <1> 	add	esi, 508
  4145                              <1> tloop_8:
  4146 00004F45 8B06                <1> 	mov	eax, [esi]
  4147 00004F47 21C0                <1> 	and	eax, eax ; 0 ?
  4148 00004F49 7409                <1> 	jz	short tloop_9
  4149                              <1> 	
  4150 00004F4B 56                  <1> 	push	esi ; **** ; 10/01/2022
  4151 00004F4C 51                  <1> 	push	ecx ; *****
  4152 00004F4D E881FCFFFF          <1> 	call	free
  4153                              <1> 		; if cf = 0 -> eax = 0
  4154                              <1> 		; if cf = 1 -> eax = error code (in al)
  4155 00004F52 59                  <1> 	pop	ecx ; *****
  4156 00004F53 5E                  <1> 	pop	esi ; **** ; 10/01/2022
  4157                              <1> 	; 10/01/2022
  4158                              <1> 	;; 07/06/2020
  4159                              <1> 	;jc	short tloop_6
  4160                              <1> tloop_9:
  4161 00004F54 83EE04              <1> 	sub	esi, 4
  4162 00004F57 E2EC                <1> 	loop	tloop_8
  4163                              <1> tloop_10:
  4164 00004F59 58                  <1> 	pop	eax ; *** ; free indirect block's itself
  4165 00004F5A E874FCFFFF          <1> 	call	free
  4166                              <1> 		;; if cf = 0 -> eax = 0
  4167                              <1> 		;; if cf = 1 -> eax = error code (in al)
  4168                              <1> 	; 10/01/2022
  4169                              <1> 	; (if we are here, there is not an error, cf=0) 
  4170                              <1> 	;jmp	short tloop_6
  4171                              <1> 
  4172                              <1> 	; 10/02/2022
  4173 00004F5F 31C0                <1> 	xor	eax, eax ; 0
  4174 00004F61 5E                  <1> 	pop	esi ; **
  4175 00004F62 5F                  <1> 	pop	edi ; *
  4176 00004F63 C3                  <1> 	retn
  4177                              <1> 
  4178                              <1> 	; Retro UNIX 386 v2.0 'imap' code
  4179                              <1> 	;	(runix v2 fs inode map)
  4180                              <1> imap:
  4181                              <1> 	; 18/04/2022
  4182                              <1> 	; 26/03/2022
  4183                              <1> 	; 12/03/2022
  4184                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  4185                              <1> 	;	(major modification)
  4186                              <1> 	; 05/11/2021 - temporary (simplified code)
  4187                              <1> 	; 21/08/2021
  4188                              <1> 	; 15/08/2021
  4189                              <1> 	; 14/06/2021
  4190                              <1> 	; 02/05/2021
  4191                              <1> 	; 01/04/2021, 08/04/2021, 24/04/2021
  4192                              <1> 	; 29/03/2021
  4193                              <1> 	; 28/03/2021 - Retro UNIX 386 v2 (beginning)
  4194                              <1> 	;
  4195                              <1> 	; 'imap' finds the byte in inode map containing
  4196                              <1> 	; allocation bit for an i-node whose number in (E)AX
  4197                              <1> 	;
  4198                              <1> 	; (ref: 'UNIXHDCP.ASM', imap', 22/01/2020) 
  4199                              <1> 	;
  4200                              <1> 	; ((Retro UNIX 386 v2 'imap' code is mostly different
  4201                              <1> 	; than Retro UNIX 386 v1.1 'imap' code.))
  4202                              <1> 	;
  4203                              <1> 	; INPUTS ->
  4204                              <1> 	;   EAX = inode number
  4205                              <1> 	;        0 = first free inode
  4206                              <1> 	;       >0 = requested inode
  4207                              <1> 	;   [cdev] = current (logical) drive/device
  4208                              <1> 	;	
  4209                              <1> 	; OUTPUTS ->
  4210                              <1> 	;    EBX = address of the byte contains allocation bit
  4211                              <1> 	;     DX has 1 at calculated bit position
  4212                              <1> 	;   ; 05/11/2021	
  4213                              <1> 	;    EBP = superblock buffer address  
  4214                              <1> 	;    (EAX = inode number)
  4215                              <1> 	;   12/03/2022
  4216                              <1> 	;    (if EAX input is 0, EAX = first free inode > 1)
  4217                              <1> 	;	 		  	
  4218                              <1> 	;   ; 08/04/2021
  4219                              <1> 	;     If cf=1 -> error code in eax (al) 	
  4220                              <1> 	;
  4221                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp
  4222                              <1> 
  4223                              <1> 	; 05/11/2021
  4224 00004F64 803D[416D0000]00    <1> 	cmp	byte [cdev], 0
  4225 00004F6B 7616                <1> 	jna	short imap_0
  4226                              <1> 	; 10/01/2022
  4227 00004F6D BD[1C700000]        <1> 	mov	ebp, mount ; mounted fs superblock buffer
  4228 00004F72 EB14                <1> 	jmp	short imap_1
  4229                              <1> 
  4230                              <1> imap_ialloc_err:
  4231                              <1> 	; 10/01/2022
  4232 00004F74 C705[D86D0000]2100- <1> 	mov	dword [u.error], ERR_INO_ALLOC ; 33
  4232 00004F7C 0000                <1>
  4233                              <1> 			; 'inode allocation error !'
  4234 00004F7E E9EAE2FFFF          <1> 	jmp	error
  4235                              <1>  
  4236                              <1> imap_0:
  4237                              <1> 	; 10/01/2022
  4238 00004F83 BD[146E0000]        <1> 	mov	ebp, systm ; root fs superblock buffer
  4239                              <1> imap_1:
  4240                              <1> 	; 26/03/2022
  4241                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4242                              <1> imap_x:
  4243                              <1> 	; 05/11/2021
  4244                              <1> 	; 21/08/2021
  4245                              <1> 	; 15/08/2021 (Retro UNIX 386 v2)
  4246                              <1> 	; call from 'maknod2' ; 10/01/2022
  4247                              <1> 	;
  4248                              <1> 	; eax = inode number
  4249                              <1> 	; [cdev] = device number for inode in eax
  4250                              <1> 	; ebp = superblock buffer address
  4251                              <1> 
  4252                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4253                              <1> 	; 'imap' and 'imap_x' will return with..
  4254                              <1> 	;    ECX = byte offset from inode map buff (imap_x)
  4255                              <1> 	;    EBX = byte addr of the byte with allocation bit
  4256                              <1> 	;    EDX (DL) has a 1 in the calculated bit position
  4257                              <1> 
  4258                              <1> 	; 02/05/2021
  4259                              <1> 	; convert inode number to first free inode if it is 0
  4260 00004F88 E83B000000          <1> 	call	imap_3 ; 10/01/2022
  4261 00004F8D 72E5                <1> 	jc	short imap_ialloc_err
  4262                              <1> 	; eax = inode number > 1 (1 = root directory inode)
  4263                              <1> 
  4264 00004F8F 898584000000        <1> 	mov	[ebp+SB.LastInode], eax
  4265                              <1> 	
  4266 00004F95 50                  <1> 	push	eax ; * ; save inode number
  4267                              <1> 
  4268                              <1> 	; convert inode number to inode map sector index
  4269 00004F96 E845000000          <1> 	call	imap_8 ; 10/01/2022
  4270 00004F9B 50                  <1> 	push	eax ; ** ; byte offset in inode map buffer
  4271                              <1> 
  4272                              <1> 	; edx = inode map buffer sector index number (< 16)
  4273                              <1> 	; eax = byte offset in inode map buffer (< 512)
  4274                              <1> 
  4275                              <1> 	; 15/08/2021
  4276 00004F9C 89958C000000        <1> 	mov	[ebp+SB.ImapIndex], edx
  4277 00004FA2 8B4520              <1> 	mov	eax, [ebp+SB.InodeMapAddr]
  4278 00004FA5 01D0                <1> 	add	eax, edx
  4279 00004FA7 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  4280                              <1> 	; eax = physical sector number
  4281                              <1> 	; [cdev] = current device/disk number
  4282                              <1> 	
  4283                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4284 00004FAA 55                  <1> 	push	ebp ; ***
  4285 00004FAB E8DE0A0000          <1> 	call	dskrd
  4286 00004FB0 5D                  <1> 	pop	ebp ; ***
  4287                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  4288                              <1> 	; eax = physical sector number
  4289                              <1> 	; ebx = buffer data address
  4290                              <1> 
  4291                              <1> 	; 26/03/2022
  4292                              <1> 	; (ecx may be > 255 at return from dskrd)
  4293                              <1> 	;sub	ecx, ecx ; 0
  4294                              <1> 	; 10/01/2022
  4295                              <1> 	;mov	cl, [esp+4] ; * ; inode number
  4296                              <1> 	; 18/04/2022
  4297 00004FB1 8B4C2404            <1> 	mov	ecx, [esp+4] ; * ; inode number
  4298 00004FB5 FEC9                <1> 	dec	cl
  4299                              <1> 	; 26/03/2022
  4300 00004FB7 31D2                <1> 	xor	edx, edx
  4301                              <1> 	;mov	dl, 1
  4302 00004FB9 FEC2                <1> 	inc	dl ; dl = 1
  4303                              <1> 	;and	ecx, 7
  4304                              <1> 	; 26/03/2022
  4305                              <1> 	; 02/05/2021
  4306                              <1> 	;dec	cl
  4307                              <1> 	;jz	short imap_2 ; 15/08/2021
  4308 00004FBB 80E107              <1> 	and	cl, 7	; 1 imap byte is for 8 inodes 
  4309                              <1> 	;jz	short imap_2
  4310 00004FBE D2E2                <1> 	shl	dl, cl
  4311                              <1> imap_2:
  4312                              <1> 	; 10/01/2022
  4313                              <1> 	; save physical sector number of imap sector in the SB
  4314 00004FC0 89457C              <1> 	mov	[ebp+SB.ImapBuffer], eax ; ! sector addr !
  4315                              <1> 	; 
  4316 00004FC3 59                  <1> 	pop	ecx ; ** ; byte offset in inode map buffer
  4317 00004FC4 01CB                <1> 	add	ebx, ecx ; + byte position
  4318 00004FC6 58                  <1> 	pop	eax ; * ; inode number
  4319                              <1> 
  4320                              <1> 	; 10/01/2022
  4321                              <1> 	; ECX contains byte offset from inode map buff (imap_x)
  4322                              <1> 	; EDX (DL) has a 1 in the calculated bit position
  4323                              <1> 	; EBX has byte address of the byte with allocation bit
  4324                              <1> 
  4325 00004FC7 C3                  <1> 	retn
  4326                              <1> 
  4327                              <1> imap_3:
  4328                              <1> 	; 10/01/2022
  4329                              <1> 	; 15/08/2021
  4330                              <1> 	; 02/05/2021
  4331                              <1> 	; 28/03/2021
  4332                              <1> 	; get first free inode number (from superblock)
  4333                              <1> 	; and check inode number against inode count
  4334                              <1> 	;
  4335                              <1> 	; INPUT:
  4336                              <1> 	;    eax = 0 -> get first free inode number
  4337                              <1> 	;    (eax > 0 -> check inode number)
  4338                              <1> 	;    ebp = superblock address ; 15/08/2021
  4339                              <1> 	; OUTPUT:
  4340                              <1> 	;    eax = inode number 
  4341                              <1> 	;    (eax will be 2 when SB.FirstFreeIno is invalid)
  4342                              <1> 	;    cf = 1 -> inode allocation error/problem
  4343                              <1> 	
  4344 00004FC8 21C0                <1> 	and	eax, eax	
  4345 00004FCA 750E                <1> 	jnz	short imap_5
  4346                              <1> 
  4347                              <1> 	; get first free inode
  4348                              <1> 	;mov	eax, [ebp+SB.FreeInodes]
  4349                              <1> 	;and	eax, eax
  4350                              <1> 	;jz	short imap_6
  4351                              <1> 	; 10/01/2022
  4352 00004FCC 394530              <1> 	cmp	[ebp+SB.FreeInodes], eax ; 0
  4353 00004FCF 760D                <1> 	jna	short imap_6	
  4354 00004FD1 8B4534              <1> 	mov	eax, [ebp+SB.FirstFreeIno] ; 1 based inode num
  4355 00004FD4 40                  <1> 	inc	eax
  4356 00004FD5 7502                <1> 	jnz	short imap_4 ; 0FFFFFFFFh -> 0
  4357                              <1> 	; invalid first free inode value (not initialized)
  4358 00004FD7 B003                <1> 	mov	al, 3 ; first free inode to be searched + 1
  4359                              <1> imap_4:
  4360 00004FD9 48                  <1> 	dec	eax
  4361                              <1> imap_5:
  4362                              <1> 	; 15/08/2021
  4363                              <1> 	; check inode number against inode count of the fs
  4364 00004FDA 394514              <1> 	cmp	[ebp+SB.InodeCount], eax
  4365 00004FDD C3                  <1> 	retn	; if cf = 1 --> inode number > inode count
  4366                              <1> imap_6:
  4367                              <1> 	; 'imap' inode allocation error !
  4368 00004FDE F9                  <1> 	stc
  4369                              <1> imap_7:
  4370 00004FDF C3                  <1> 	retn
  4371                              <1> 
  4372                              <1> imap_8:
  4373                              <1> 	; 10/01/2022
  4374                              <1> 	; 15/08/2021
  4375                              <1> 	; 02/05/2021
  4376                              <1> 	; 28/03/2021
  4377                              <1> 	; convert inode count to inode map sector index
  4378                              <1> 	;
  4379                              <1> 	; INPUT: 
  4380                              <1> 	;    eax = inode number
  4381                              <1> 	; OUTPUT:
  4382                              <1> 	;    edx = inode map sector offset/index number
  4383                              <1> 	;    eax = byte offset from start of imapbuf	 
  4384                              <1> 
  4385 00004FE0 31D2                <1> 	xor	edx, edx
  4386 00004FE2 48                  <1> 	dec	eax ; zero based inode number
  4387 00004FE3 74FA                <1> 	jz	short imap_7
  4388                              <1> 
  4389 00004FE5 C1E803              <1> 	shr	eax, 3 ; 8 inodes per inode map byte
  4390                              <1> 		; eax = byte offset from start of inode map
  4391 00004FE8 88E2                <1> 	mov	dl, ah ; ah <= 31 (1Fh) for Retro UNIX 386 v2
  4392 00004FEA D0EA                <1> 	shr	dl, 1
  4393                              <1> 		; edx = inode map sector offset/index number
  4394                              <1> 	;and	eax, 511
  4395 00004FEC 6625FF01            <1> 	and	ax, 511
  4396                              <1> 		; eax = byte offset from start of imapbuf
  4397 00004FF0 C3                  <1> 	retn
  2092                                  %include 'u6.s'      ; 31/05/2015
  2093                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2094                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2095                              <1> ; ****************************************************************************
  2096                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.3) - SYS6.INC
  2097                              <1> ; Last Modification: 15/07/2022
  2098                              <1> ; ----------------------------------------------------------------------------
  2099                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2100                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2101                              <1> ;
  2102                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2103                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2104                              <1> ; <Bell Laboratories (17/3/1972)>
  2105                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2106                              <1> ;
  2107                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2108                              <1> ;
  2109                              <1> ; ****************************************************************************
  2110                              <1> 
  2111                              <1> 	; 09/03/2022
  2112                              <1> 	; 25/12/2021
  2113                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2114                              <1> readi:
  2115                              <1> 	; 20/05/2015
  2116                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2117                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2118                              <1> 	;
  2119                              <1> 	; Reads from an inode whose number in R1
  2120                              <1> 	; 
  2121                              <1> 	; INPUTS ->
  2122                              <1> 	;    r1 - inode number
  2123                              <1> 	;    u.count - byte count user desires
  2124                              <1> 	;    u.base - points to user buffer
  2125                              <1> 	;    u.fofp - points to word with current file offset
  2126                              <1> 	; OUTPUTS ->
  2127                              <1> 	;    u.count - cleared
  2128                              <1> 	;    u.nread - accumulates total bytes passed back
  2129                              <1> 	;
  2130                              <1> 	; ((AX = R1)) input/output
  2131                              <1> 	;    (Retro UNIX Prototype: 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2132                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, edi)) -15/07/2022- 
  2133                              <1> 
  2134 00004FF1 31D2                <1> 	xor	edx, edx ; 0
  2135 00004FF3 8915[906D0000]      <1> 	mov 	[u.nread], edx ; 0
  2136                              <1> 		; clr u.nread / accumulates number of bytes transmitted
  2137 00004FF9 668915[D06D0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2138 00005000 3915[8C6D0000]      <1> 	cmp 	[u.count], edx ; 0
  2139                              <1> 		; tst u.count / is number of bytes to be read greater than 0
  2140 00005006 7701                <1> 	ja 	short readi_1 ; 1f
  2141                              <1> 		; bgt 1f / yes, branch
  2142 00005008 C3                  <1> 	retn
  2143                              <1> 		; rts r0 / no, nothing to read; return to caller
  2144                              <1> readi_1: ; 1:
  2145                              <1> 	;	; mov r1,-(sp) / save i-number on stack
  2146                              <1> 	;cmp	ax, 40
  2147                              <1> 	;	; cmp r1,$40. / want to read a special file 
  2148                              <1> 	;	;             / (i-nodes 1,...,40 are for special files)
  2149                              <1>         ;ja	dskr 
  2150                              <1> 	;	; ble 1f / yes, branch
  2151                              <1> 	;	; jmp dskr / no, jmp to dskr; 
  2152                              <1> 	;	;         / read file with i-node number (r1)
  2153                              <1> 	;	;    / starting at byte ((u.fofp)), read in u.count bytes
  2154                              <1> 	
  2155                              <1> 	; 28/11/2021
  2156 00005009 F605[D66D0000]FF    <1> 	test	byte [u.kcall], 0FFh
  2157                              <1> 	;jnz	short readi_2  ; 'readi' called by 'namei'
  2158                              <1> 	; 09/03/2022
  2159                              <1> 	;jz	short _readi_2
  2160                              <1> 	;jmp	dskr
  2161 00005010 750C                <1> 	jnz	short readi_2 ; 'readi' called by 'namei'
  2162                              <1> ;_readi_2:	; 09/03/2022
  2163                              <1> 	; eax = inode number
  2164                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2165 00005012 E86EFCFFFF          <1> 	call	iget
  2166                              <1> ;readi_2:
  2167                              <1> 	; 28/11/2021
  2168                              <1> 	; eax = inode number
  2169                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2170 00005017 E8F6040000          <1> 	call	is_regular_file
  2171                              <1> 	;jz	dskr ; regular file 
  2172                              <1> 	; 25/12/2021
  2173 0000501C 7505                <1> 	jnz	short readi_5 ; device file 
  2174                              <1> readi_2:	 ; 09/03/2022
  2175                              <1> 	; regular file
  2176 0000501E E9E3000000          <1> 	jmp	dskr
  2177                              <1> readi_5:
  2178                              <1> 	; (20/05/2015)
  2179 00005023 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2180                              <1> 
  2181                              <1> 	; 28/11/2021	
  2182                              <1> 	; device file
  2183 00005024 BB[3E500000]        <1> 	mov	ebx, readi_4
  2184 00005029 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2185 0000502C 720E                <1> 	jb	short readi_3
  2186 0000502E 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2187 00005031 7709                <1> 	ja	short readi_3	
  2188                              <1> 	
  2189                              <1> 	; convert v2 inode number to v1 device inode number
  2190 00005033 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2191 00005035 89C1                <1> 	mov	ecx, eax
  2192 00005037 C0E102              <1> 	shl	cl, 2 ; * 4
  2193 0000503A 01CB                <1> 	add	ebx, ecx
  2194                              <1> readi_3:
  2195 0000503C FF23                <1> 	jmp	dword [ebx]	
  2196                              <1> 		 ; jmp *1f-2(r1)
  2197                              <1> readi_4: ; 1:
  2198 0000503E [8E500000]          <1> 	dd	null ; 28/11/2021
  2199 00005042 [92500000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2200                              <1> 		 ;rtty / tty; r1=2
  2201                              <1> 		 ;rppt / ppt; r1=4
  2202 00005046 [E2500000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2203                              <1> 		 ;rmem / mem; r1=6
  2204                              <1> 		 ;rrf0 / rf0
  2205                              <1> 		 ;rrk0 / rk0
  2206                              <1> 		 ;rtap / tap0
  2207                              <1> 		 ;rtap / tap1
  2208                              <1> 		 ;rtap / tap2
  2209                              <1> 		 ;rtap / tap3
  2210                              <1> 		 ;rtap / tap4
  2211                              <1> 		 ;rtap / tap5
  2212                              <1> 		 ;rtap / tap6
  2213                              <1> 		 ;rtap / tap7
  2214 0000504A [57590000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2215 0000504E [57590000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2216 00005052 [57590000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2217 00005056 [57590000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2218 0000505A [57590000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2219 0000505E [57590000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2220 00005062 [F7500000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2221 00005066 [DE500000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2222                              <1> 		 ;rcvt / tty0
  2223 0000506A [DE500000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2224                              <1> 		 ;rcvt / tty1
  2225 0000506E [DE500000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2226                              <1> 		 ;rcvt / tty2
  2227 00005072 [DE500000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2228                              <1> 		 ;rcvt / tty3
  2229 00005076 [DE500000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2230                              <1> 		 ;rcvt / tty4
  2231 0000507A [DE500000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2232                              <1> 		 ;rcvt / tty5
  2233 0000507E [DE500000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2234                              <1> 		 ;rcvt / tty6
  2235 00005082 [DE500000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2236                              <1> 		 ;rcvt / tty7
  2237 00005086 [DE500000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2238                              <1> 		 ;rcrd / crd
  2239 0000508A [DE500000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2240                              <1> 
  2241                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2242                              <1> null:
  2243 0000508E 31C0                <1> 	xor	eax, eax
  2244 00005090 58                  <1> 	pop	eax
  2245 00005091 C3                  <1> 	retn
  2246                              <1> 
  2247                              <1> 	; 11/01/2022
  2248                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2249                              <1> rtty: ; / read from console tty
  2250                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2251                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2252                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2253                              <1> 	;	     must be written immediate on video page (screen)
  2254                              <1> 	;	     when it is required.	
  2255                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2256                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2257                              <1> 	;
  2258                              <1> 	; Console tty buffer is PC keyboard buffer
  2259                              <1> 	; and keyboard-keystroke handling is different than original
  2260                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2261                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2262                              <1> 	;
  2263                              <1> 	; 06/12/2013
  2264 00005092 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2265 00005099 8A83[63690000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2266                              <1> rttys:
  2267                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2268                              <1> 	               ; / of the control and status block
  2269                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2270                              <1> 		       ; / tty buffer
  2271                              <1> 	; 28/07/2013
  2272 0000509F A2[996D0000]        <1> 	mov 	[u.ttyn], al
  2273                              <1> 	; 13/01/2014
  2274 000050A4 FEC0                <1> 	inc	al
  2275 000050A6 A2[9A6D0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2276                              <1> rtty_nc: ; 01/02/2014
  2277                              <1> 	; 29/09/2013
  2278                              <1> 	;mov	ecx, 10
  2279                              <1> 	; 11/01/2022
  2280 000050AB 29C9                <1> 	sub	ecx, ecx
  2281 000050AD B10A                <1> 	mov	cl, 10
  2282                              <1> rtty_1: 	; 01/02/2014
  2283                              <1> 	;push 	cx ; 29/09/2013
  2284                              <1> 	; 11/12/2021
  2285 000050AF 51                  <1> 	push	ecx
  2286                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2287 000050B0 B001                <1> 	mov 	al, 1
  2288 000050B2 E8B00B0000          <1> 	call 	getc
  2289                              <1> 	;pop 	cx ; 29/09/2013	
  2290                              <1> 	; 11/12/2021
  2291 000050B7 59                  <1> 	pop	ecx
  2292 000050B8 7516                <1> 	jnz	short rtty_2
  2293                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2294                              <1> 	               ; / of chars. Is this number non-zero?
  2295 000050BA E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2296                              <1> 	; 05/10/2013
  2297 000050BC 8A25[996D0000]      <1> 	mov	ah, [u.ttyn]
  2298                              <1> 	; 29/09/2013
  2299 000050C2 E8C6F7FFFF          <1> 	call	sleep
  2300                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2301                              <1>                 ;           / (120 chars.)
  2302                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2303 000050C7 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2304                              <1> 
  2305                              <1> rtty_idle:
  2306                              <1> 	; 29/07/2013
  2307 000050C9 E832F7FFFF          <1> 	call 	idle
  2308 000050CE EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2309                              <1> 	;1:
  2310                              <1> 		; tst 2(r5) / is the number of characters zero
  2311                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2312                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2313                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2314                              <1> 		          ; / contains the next char.
  2315                              <1> 		; dec 2(r5) / decrement the character count
  2316                              <1> rtty_2:
  2317 000050D0 30C0                <1> 	xor 	al, al
  2318 000050D2 E8900B0000          <1> 	call 	getc
  2319 000050D7 E891000000          <1> 	call	passc
  2320                              <1> 		; jsr r0,passc / move the character to core (user)
  2321                              <1> 	;; 17/10/2015 - 16/07/2015
  2322                              <1> 	; 19/06/2014
  2323                              <1> 	;;jnz	short rtty_nc
  2324 000050DC 58                  <1> 	pop	eax  ; (20/05/2015)
  2325 000050DD C3                  <1> 	retn 
  2326                              <1> ;ret1:
  2327                              <1> 		; jmp ret / return to caller via 'ret'
  2328                              <1> 
  2329                              <1> rcvt:   ; < receive/read character from tty >
  2330                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2331                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2332                              <1> 	;
  2333                              <1> 	; Retro UNIX 8086 v1 modification !
  2334                              <1> 	; 
  2335                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2336                              <1> 	;		(exactly different than this one)
  2337                              <1> 	;	was in 'u9.s' file.
  2338                              <1> 	;
  2339 000050DE 2C0A                <1> 	sub 	al, 10
  2340                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2341                              <1> 	; 16/07/2013
  2342                              <1> 	; 21/05/2013
  2343 000050E0 EBBD                <1>         jmp     short rttys
  2344                              <1>       
  2345                              <1> ;rppt: / read paper tape
  2346                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2347                              <1> ;			 / places
  2348                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2349                              <1> ;		       / also enables read bit in prs
  2350                              <1> ;	jsr	r0,passc / place character in users buffer area
  2351                              <1> ;	br	rppt
  2352                              <1> 
  2353                              <1> rmem: ; / transfer characters from memory to a user area of core
  2354                              <1> 	; 17/10/2015
  2355                              <1> 	; 11/06/2015
  2356                              <1> 	; 24/05/2015
  2357                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2358                              <1> 	;
  2359 000050E2 8B35[786D0000]      <1> 	mov     esi, [u.fofp]
  2360                              <1> rmem_1:
  2361 000050E8 8B1E                <1>         mov     ebx, [esi]        
  2362                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2363                              <1> 		               ; / to be transferred to user
  2364 000050EA FF06                <1>         inc     dword [esi] ; 17/10/2015
  2365                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2366                              <1> 			    ; / char in memory file
  2367 000050EC 8A03                <1> 	mov	al, [ebx]
  2368                              <1> 		; movb (r1),r1 / get character from memory file, 
  2369                              <1> 		             ; / put it in r1
  2370 000050EE E87A000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2371                              <1> 			     ;  / the next byte of the users core area
  2372                              <1> 		; br rmem / continue
  2373 000050F3 75F3                <1> 	jnz	short rmem_1
  2374                              <1> ret_:
  2375 000050F5 58                  <1> 	pop	eax ; 09/06/2015
  2376 000050F6 C3                  <1> 	retn
  2377                              <1> 
  2378                              <1> rlpr:
  2379                              <1> ;1:
  2380                              <1> ;rcrd:
  2381 000050F7 C705[D86D0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2381 000050FF 0000                <1>
  2382 00005101 E967E1FFFF          <1> 	jmp	error
  2383                              <1> 		;jmp	error / see 'error' routine
  2384                              <1> 
  2385                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2386                              <1> dskr:
  2387                              <1> 	; 12/10/2015
  2388                              <1> 	; 21/08/2015
  2389                              <1> 	; 25/07/2015
  2390                              <1> 	; 10/07/2015
  2391                              <1> 	; 16/06/2015
  2392                              <1> 	; 31/05/2015
  2393                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2394                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2395                              <1> dskr_0:
  2396 00005106 50                  <1> 	push	eax
  2397                              <1> 		; mov (sp),r1 / i-number in r1
  2398                              <1> 	; AX = i-number
  2399 00005107 E879FBFFFF          <1> 	call	iget
  2400                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2401                              <1>         ;movzx	edx, word [i.size] ; 16/06/2015
  2402                              <1> 	;	; mov i.size,r2 / file size in bytes in r2
  2403                              <1> 	; 28/11/2021
  2404 0000510C 8B15[EC680000]      <1> 	mov	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2405                              <1> 	;
  2406 00005112 8B1D[786D0000]      <1> 	mov	ebx, [u.fofp]
  2407 00005118 2B13                <1> 	sub	edx, [ebx]
  2408                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2409                              <1>         ; 12/10/2015
  2410                              <1> 	; jna	short ret_ 
  2411                              <1> 		; blos ret
  2412 0000511A 7709                <1> 	ja	short dskr_1
  2413                              <1> 	;
  2414                              <1> dskr_retn: ; 12/10/2015
  2415 0000511C 58                  <1> 	pop	eax
  2416 0000511D C605[D66D0000]00    <1> 	mov	byte [u.kcall], 0
  2417 00005124 C3                  <1> 	retn	
  2418                              <1> dskr_1: 
  2419 00005125 3B15[8C6D0000]      <1> 	cmp     edx, [u.count] 
  2420                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2421                              <1> 			       ; / to carry out read
  2422 0000512B 7306                <1> 	jnb	short dskr_2
  2423                              <1> 		; bhis 1f
  2424 0000512D 8915[8C6D0000]      <1> 	mov	[u.count], edx
  2425                              <1> 		; mov r2,u.count / no, just read to end of file
  2426                              <1> dskr_2: ; 1:
  2427                              <1> 	; (E)AX = i-number ; 28/11/2021 (32 bit inode number)
  2428                              <1> 	;call	mget
  2429                              <1> 		; jsr r0,mget / returns physical block number of block 
  2430                              <1> 		    ; / in file where offset points
  2431                              <1> 	; 28/11/2021
  2432 00005133 E8D6F7FFFF          <1> 	call	mget_r
  2433                              <1> 
  2434                              <1> 	; eax = physical block number
  2435                              <1> 	; [cdev] = current device number 
  2436 00005138 E851090000          <1> 	call	dskrd
  2437                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2438                              <1> 			     ; / 1st word of data in buffer
  2439                              <1> 	; 09/06/2015
  2440 0000513D 803D[D66D0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2441 00005144 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2442 00005146 66833D[D06D0000]00  <1> 	cmp	word [u.pcount], 0
  2443 0000514E 7705                <1> 	ja	short dskr_4
  2444                              <1> dskr_3:
  2445                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2446 00005150 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2447                              <1> dskr_4:
  2448                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2449 00005155 E837030000          <1> 	call	sioreg
  2450                              <1> 		; jsr r0,sioreg
  2451 0000515A 87F7                <1> 	xchg	esi, edi
  2452                              <1> 	; edi = file (user data) offset
  2453                              <1> 	; edi = sector (I/O) buffer offset
  2454                              <1> 	; ecx = byte count
  2455 0000515C F3A4                <1> 	rep	movsb
  2456                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2457                              <1> 		                 ; / starting at u.base
  2458                              <1> 		; dec r3
  2459                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2460                              <1> 	; 25/07/2015
  2461                              <1> 	; eax = remain bytes in buffer
  2462                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2463 0000515E 09C0                <1> 	or	eax, eax
  2464 00005160 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2465                              <1> 	; 03/08/2013
  2466                              <1> 	;pop	eax
  2467 00005162 390D[8C6D0000]      <1> 	cmp	[u.count], ecx ; 0
  2468                              <1> 		; tst u.count / all bytes read off disk
  2469                              <1> 		; bne dskr
  2470                              <1> 		; br ret
  2471                              <1>         ;ja	short dskr_0
  2472                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2473                              <1> 	;retn
  2474                              <1> 	; 12/10/2015
  2475 00005168 76B2                <1> 	jna	short dskr_retn
  2476 0000516A 58                  <1> 	pop	eax  ; (i-node number)
  2477 0000516B EB99                <1> 	jmp	short dskr_0
  2478                              <1> 	
  2479                              <1> passc:
  2480                              <1> 	; 18/10/2015
  2481                              <1> 	; 10/07/2015
  2482                              <1> 	; 01/07/2015
  2483                              <1> 	; 08/06/2015
  2484                              <1> 	; 04/06/2015
  2485                              <1> 	; 20/05/2015
  2486                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2487                              <1> 	;
  2488                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2489                              <1> 	;		      to physical address
  2490 0000516D 66833D[D06D0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2491                              <1> 			     ; 1-4095 --> use previous physical base address
  2492                              <1> 			     ; in [u.pbase]
  2493 00005175 7705                <1> 	ja	short passc_3
  2494                              <1> 	; 08/06/2015 - 10/07/2015
  2495 00005177 E82C000000          <1> 	call	trans_addr_w
  2496                              <1> passc_3:
  2497                              <1> 	; 19/05/2015
  2498 0000517C 66FF0D[D06D0000]    <1> 	dec	word [u.pcount]
  2499                              <1> 	;
  2500 00005183 8B1D[CC6D0000]      <1> 	mov	ebx, [u.pbase]
  2501 00005189 8803                <1> 	mov	[ebx], al
  2502                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2503                              <1> 		               ; / users buffer
  2504 0000518B FF05[886D0000]      <1> 	inc	dword [u.base]
  2505                              <1> 		; inc u.base / increment the pointer to point to 
  2506                              <1> 			  ; / the next byte in users buffer
  2507 00005191 FF05[CC6D0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2508 00005197 FF05[906D0000]      <1> 	inc	dword [u.nread]
  2509                              <1> 		; inc u.nread / increment the number of bytes read
  2510 0000519D FF0D[8C6D0000]      <1> 	dec	dword [u.count]
  2511                              <1> 		; dec u.count / decrement the number of bytes to be read
  2512                              <1> 		; bne 1f / any more bytes to read? ; yes, branch
  2513 000051A3 C3                  <1> 	retn
  2514                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2515                              <1> 		             ; / 'readi' by:
  2516                              <1> 		;/ (1) pop the return address off the stack into r0
  2517                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2518                              <1> 	;1:
  2519                              <1> 		; clr	*$ps / clear processor status
  2520                              <1> 		; rts r0 / return to address currently on top of stack
  2521                              <1> 
  2522                              <1> trans_addr_r:
  2523                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2524                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2525                              <1> 	; Translate virtual address to physical address 
  2526                              <1> 	; for reading from user's memory space
  2527                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2528                              <1> 	; 18/10/2015
  2529                              <1> 	; 10/07/2015
  2530                              <1> 	; 09/06/2015
  2531                              <1> 	; 08/06/2015 
  2532                              <1> 	; 04/06/2015
  2533                              <1> 	;
  2534                              <1> 	; 18/10/2015
  2535 000051A4 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2536 000051A6 EB04                <1> 	jmp 	short trans_addr_rw
  2537                              <1> 
  2538                              <1> 	;push	eax
  2539                              <1> 	;push	ebx
  2540                              <1> 	;mov	ebx, [u.base]
  2541                              <1> 	;call	get_physical_addr ; get physical address
  2542                              <1> 	;;jnc	short cpass_0
  2543                              <1> 	;jnc	short passc_1
  2544                              <1> 	;mov	[u.error], eax
  2545                              <1> 	;;pop	ebx
  2546                              <1> 	;;pop	eax
  2547                              <1> 	;jmp	error
  2548                              <1> ;cpass_0:
  2549                              <1> 	; 18/10/2015
  2550                              <1> 	; 20/05/2015
  2551                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2552                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2553                              <1> 	;pop	ebx
  2554                              <1> 	;pop	eax
  2555                              <1> 	;retn	; 08/06/2015
  2556                              <1> 
  2557                              <1> trans_addr_w:
  2558                              <1> 	; 31/12/2021
  2559                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2560                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2561                              <1> 	; Translate virtual address to physical address
  2562                              <1> 	; for writing to user's memory space
  2563                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2564                              <1> 	; 18/10/2015
  2565                              <1> 	; 29/07/2015
  2566                              <1> 	; 10/07/2015
  2567                              <1> 	; 09/06/2015
  2568                              <1> 	; 08/06/2015
  2569                              <1> 	; 04/06/2015 (passc)
  2570                              <1> 	;
  2571                              <1> 	; 18/10/2015
  2572 000051A8 29D2                <1> 	sub	edx, edx
  2573 000051AA FEC2                <1> 	inc	dl ; 1 (write access sign)
  2574                              <1> trans_addr_rw:
  2575 000051AC 50                  <1> 	push	eax
  2576 000051AD 53                  <1> 	push	ebx
  2577                              <1> 	; 18/10/2015
  2578 000051AE 52                  <1> 	push 	edx ; r/w sign (in DL)
  2579                              <1> 	;
  2580 000051AF 8B1D[886D0000]      <1> 	mov	ebx, [u.base]
  2581 000051B5 E816D7FFFF          <1> 	call	get_physical_addr ; get physical address
  2582 000051BA 730A                <1> 	jnc	short passc_0
  2583 000051BC A3[D86D0000]        <1> 	mov	[u.error], eax
  2584                              <1> 	;pop	edx
  2585                              <1> 	;pop 	ebx
  2586                              <1> 	;pop	eax
  2587 000051C1 E9A7E0FFFF          <1> 	jmp	error
  2588                              <1> passc_0:
  2589 000051C6 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2590 000051C9 5A                  <1> 	pop	edx ; 18/10/2015
  2591 000051CA 7517                <1> 	jnz	short passc_1
  2592                              <1> 	; 18/10/2015
  2593 000051CC 20D2                <1> 	and 	dl, dl
  2594 000051CE 7413                <1> 	jz	short passc_1
  2595                              <1> 	; 20/05/2015
  2596                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2597                              <1> 	; EBX = linear address
  2598 000051D0 51                  <1> 	push 	ecx
  2599                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix)
  2600 000051D1 53                  <1> 	push	ebx ;* ; BugFix  ; 31/12/2021
  2601 000051D2 E868D6FFFF          <1> 	call 	copy_page
  2602 000051D7 5B                  <1> 	pop	ebx ;* ; BugFix  ; 31/12/2021
  2603 000051D8 59                  <1> 	pop	ecx
  2604 000051D9 7217                <1> 	jc	short passc_2
  2605                              <1> 	; 30/11/2021
  2606                              <1> 	;push	eax ; physical address of the new/allocated page
  2607                              <1> 	;call	add_to_swap_queue
  2608                              <1> 	;pop	eax
  2609                              <1> 	; 18/10/2015
  2610 000051DB 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2611                              <1> 	;mov 	ecx, PAGE_SIZE
  2612                              <1> 	;sub	ecx, ebx 
  2613 000051E1 01D8                <1> 	add	eax, ebx  
  2614                              <1> passc_1: 
  2615                              <1> 	; 18/10/2015
  2616                              <1> 	; 20/05/2015
  2617 000051E3 A3[CC6D0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2618 000051E8 66890D[D06D0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2619 000051EF 5B                  <1> 	pop	ebx
  2620 000051F0 58                  <1> 	pop	eax
  2621 000051F1 C3                  <1> 	retn	; 08/06/2015
  2622                              <1> passc_2:
  2623 000051F2 C705[D86D0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2623 000051FA 0000                <1>
  2624                              <1> 	;pop 	ebx
  2625                              <1> 	;pop	eax
  2626 000051FC E96CE0FFFF          <1> 	jmp	error
  2627                              <1> 
  2628                              <1> 	; 09/03/2022
  2629                              <1> 	; 25/12/2021
  2630                              <1> 	; 11/12/2021
  2631                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2632                              <1> writei:
  2633                              <1> 	; 20/05/2015
  2634                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2635                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2636                              <1> 	;
  2637                              <1> 	; Write data to file with inode number in R1
  2638                              <1> 	; 
  2639                              <1> 	; INPUTS ->
  2640                              <1> 	;    r1 - inode number
  2641                              <1> 	;    u.count - byte count to be written
  2642                              <1> 	;    u.base - points to user buffer
  2643                              <1> 	;    u.fofp - points to word with current file offset
  2644                              <1> 	; OUTPUTS ->
  2645                              <1> 	;    u.count - cleared
  2646                              <1> 	;    u.nread - accumulates total bytes passed back	
  2647                              <1> 	; ((AX = R1))
  2648                              <1> 	;    (Retro UNIX Prototype: 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2649                              <1> 	;    ((Modified registers: edx, ebx, ecx, esi, edi)) -15/07/2022-	
  2650                              <1> 
  2651 00005201 31C9                <1> 	xor	ecx, ecx
  2652 00005203 890D[906D0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2653                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2654                              <1> 		            ; / read or write calls
  2655 00005209 66890D[D06D0000]    <1> 	mov	[u.pcount], cx	; 19/05/2015
  2656 00005210 390D[8C6D0000]      <1> 	cmp 	[u.count], ecx
  2657                              <1> 	;	; tst u.count / test the byte count specified by the user
  2658 00005216 770B                <1> 	ja 	short writei_1	; 1f
  2659                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2660                              <1> 
  2661                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2
  2662 00005218 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2663 0000521B 7505                <1> 	jne	short writei_0
  2664 0000521D E943010000          <1> 	jmp	lpr_stat	; get/read line status
  2665                              <1> writei_0:
  2666 00005222 C3                  <1> 	retn
  2667                              <1> 	;	; rts r0 / no, return - no writing to do
  2668                              <1> writei_1: ;1:
  2669                              <1> 	;	; mov r1 ,-(sp) / save the i-node number on the stack
  2670                              <1> 	;cmp 	ax, 40
  2671                              <1> 	;	; cmp r1,$40.
  2672                              <1> 	;	; / does the i-node number indicate a special file?
  2673                              <1>         ;ja	dskw 
  2674                              <1> 	;	; bgt dskw / no, branch to standard file output
  2675                              <1> 
  2676                              <1> 	; 28/11/2021
  2677 00005223 F605[D66D0000]FF    <1> 	test	byte [u.kcall], 0FFh
  2678 0000522A 750C                <1> 	jnz	short writei_2  ; 'writei' called by 'mkdir'
  2679                              <1> 
  2680                              <1> 	; eax = inode number
  2681                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2682 0000522C E854FAFFFF          <1> 	call	iget
  2683                              <1> ;writei_2:
  2684                              <1> 	; 28/11/2021
  2685                              <1> 	; eax = inode number
  2686                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2687 00005231 E8DC020000          <1> 	call	is_regular_file
  2688                              <1> 	;jz	dskw ; regular file 
  2689                              <1> 	; 25/12/2021
  2690 00005236 7505                <1> 	jnz	short writei_5 ; device file
  2691                              <1> writei_2:	 ; 09/03/2022 
  2692                              <1> 	; regular file
  2693 00005238 E968010000          <1> 	jmp	dskw
  2694                              <1> writei_5:
  2695                              <1> 	; (20/05/2015)
  2696 0000523D 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2697                              <1> 	
  2698                              <1> 	; 28/11/2021	
  2699                              <1> 	; device file
  2700 0000523E BB[58520000]        <1> 	mov	ebx, writei_4
  2701 00005243 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2702 00005246 720E                <1> 	jb	short writei_3
  2703 00005248 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2704 0000524B 7709                <1> 	ja	short writei_3 ; 11/12/2021	
  2705                              <1> 	
  2706                              <1> 	; convert v2 inode number to v1 device inode number
  2707 0000524D 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2708 0000524F 89C1                <1> 	mov	ecx, eax
  2709 00005251 C0E102              <1> 	shl	cl, 2 ; * 4
  2710 00005254 01CB                <1> 	add	ebx, ecx
  2711                              <1> writei_3:
  2712 00005256 FF23                <1> 	jmp	dword [ebx]	
  2713                              <1> 		; jmp *1f-2(r1)
  2714                              <1> 		; / jump table and jump to the appropriate routine
  2715                              <1> writei_4: ;1:
  2716 00005258 [8E500000]          <1> 	dd	null ; 28/11/2021
  2717 0000525C [A8520000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2718                              <1> 		 ;wtty / tty; r1=2
  2719                              <1> 		 ;wppt / ppt; r1=4
  2720 00005260 [FB520000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2721                              <1> 		 ;wmem / mem; r1=6
  2722                              <1> 		 ;wrf0 / rf0
  2723                              <1> 		 ;wrk0 / rk0
  2724                              <1> 		 ;wtap / tap0
  2725                              <1> 		 ;wtap / tap1
  2726                              <1> 		 ;wtap / tap2
  2727                              <1> 		 ;wtap / tap3
  2728                              <1> 		 ;wtap / tap4
  2729                              <1> 		 ;wtap / tap5
  2730                              <1> 		 ;wtap / tap6
  2731                              <1> 		 ;wtap / tap7
  2732 00005264 [C8590000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2733 00005268 [C8590000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2734 0000526C [C8590000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2735 00005270 [C8590000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2736 00005274 [C8590000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2737 00005278 [C8590000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2738 0000527C [2B530000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2739 00005280 [F5520000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2740                              <1> 		 ;xmtt / tty0
  2741 00005284 [F5520000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2742                              <1> 		 ;xmtt / tty1
  2743 00005288 [F5520000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2744                              <1> 		 ;xmtt / tty2
  2745 0000528C [F5520000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2746                              <1> 		 ;xmtt / tty3
  2747 00005290 [F5520000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2748                              <1> 		 ;xmtt / tty4
  2749 00005294 [F5520000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2750                              <1> 		 ;xmtt / tty5
  2751 00005298 [F5520000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2752                              <1> 		 ;xmtt / tty6
  2753 0000529C [F5520000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2754                              <1> 		 ;xmtt / tty7
  2755 000052A0 [F5520000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2756                              <1> 		; / wlpr / lpr
  2757 000052A4 [F5520000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)
  2758                              <1> 
  2759                              <1> ;	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2760                              <1> ;null:
  2761                              <1> ;	xor	eax, eax
  2762                              <1> ;	pop	eax
  2763                              <1> ;	retn	
  2764                              <1> 
  2765                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2766                              <1> wtty: ; write to console tty (write to screen)
  2767                              <1> 	; 18/11/2015
  2768                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2769                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2770                              <1> 	;
  2771                              <1> 	; Console tty output is on current video page
  2772                              <1> 	; Console tty character output procedure is changed here
  2773                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2774                              <1> 	;
  2775 000052A8 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2776 000052AF 8AA3[63690000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2777 000052B5 88E0                <1> 	mov	al, ah ; 07/07/2014
  2778                              <1> wttys:	
  2779                              <1> 	; 10/10/2013
  2780 000052B7 8825[996D0000]      <1> 	mov 	[u.ttyn], ah
  2781                              <1> 	; 13/01/2014
  2782 000052BD FEC0                <1> 	inc	al
  2783 000052BF A2[9B6D0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2784                              <1> wtty_nc: ; 15/05/2013
  2785                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2786 000052C4 E868010000          <1> 	call	cpass
  2787                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2788                              <1> 		             ; / none go to return address in syswrite
  2789                              <1> 		; tst r1 / is character = null
  2790                              <1> 		; beq wtty / yes, get next character
  2791                              <1> 	; 10/10/2013
  2792 000052C9 7428                <1> 	jz	short wret
  2793                              <1> 	;1 :
  2794                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2795                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2796                              <1> 		;	          / than 20
  2797                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2798                              <1> 	; 27/06/2014
  2799                              <1> wtty_1:
  2800                              <1> 	; AH = tty number
  2801                              <1> 	; AL = ASCII code of the character
  2802                              <1> 	; 15/04/2014
  2803                              <1> 	;push	ax
  2804                              <1> 	; 11/12/2021
  2805 000052CB 50                  <1> 	push	eax
  2806 000052CC E8040A0000          <1> 	call	putc ; 14/05/2013
  2807 000052D1 731D                <1> 	jnc	short wtty_2
  2808                              <1> 	; 18/11/2015
  2809 000052D3 E828F5FFFF          <1> 	call	idle
  2810                              <1> 	;mov	ax, [esp]
  2811                              <1> 	; 11/12/2021
  2812 000052D8 8B0424              <1> 	mov	eax, [esp]
  2813 000052DB E8F5090000          <1> 	call	putc
  2814 000052E0 730E                <1> 	jnc	short wtty_2 
  2815                              <1> 	; 02/06/2014
  2816 000052E2 8A25[996D0000]      <1> 	mov	ah, [u.ttyn]
  2817 000052E8 E8A0F5FFFF          <1> 	call	sleep
  2818                              <1> 	;pop	ax
  2819                              <1> 	; 11/12/2021
  2820 000052ED 58                  <1> 	pop	eax
  2821 000052EE EBDB                <1> 	jmp 	short wtty_1
  2822                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2823                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2824                              <1> 			      ; / console tty and
  2825                              <1> 		; br 	2f / place character in list; if none available
  2826                              <1> 		   	  ; / branch to put process to sleep
  2827                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2828                              <1> wtty_2:
  2829                              <1> 	; 15/04/2014
  2830                              <1> 	;pop	ax
  2831                              <1> 	; 11/12/2021
  2832 000052F0 58                  <1> 	pop	eax
  2833 000052F1 EBD1                <1> 	jmp	short wtty_nc
  2834                              <1> 		; br wtty
  2835                              <1> wret:	; 10/10/2013 (20/05/2015)
  2836 000052F3 58                  <1> 	pop	eax
  2837 000052F4 C3                  <1> 	retn
  2838                              <1> 	;2:
  2839                              <1> 		;mov	r1,-(sp) / place character on stack
  2840                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2841                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2842                              <1> 		;br	1b / try again to place character in clist and output
  2843                              <1> 
  2844                              <1> xmtt:   ; < send/write character to tty >
  2845                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2846                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2847                              <1> 	;
  2848                              <1> 	; Retro UNIX 8086 v1 modification !
  2849                              <1> 	; 
  2850                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2851                              <1> 	;		(exactly different than this one)
  2852                              <1> 	;	was in 'u9.s' file.
  2853                              <1> 	;
  2854 000052F5 2C0A                <1> 	sub 	al, 10
  2855                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2856                              <1> 	; 10/10/2013
  2857 000052F7 88C4                <1> 	mov	ah, al
  2858                              <1> 	; 28/07/2013
  2859 000052F9 EBBC                <1> 	jmp	short wttys
  2860                              <1> 
  2861                              <1> ;wppt:
  2862                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2863                              <1> ;		         / if none return to writei's calling routine
  2864                              <1> ;	jsr	r0,pptoc / output character on ppt
  2865                              <1> ;	br	wppt
  2866                              <1> 
  2867                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2868                              <1> 	; 17/10/2015
  2869                              <1> 	; 11/06/2015
  2870                              <1> 	; 24/05/2015
  2871                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2872                              <1> 	;
  2873 000052FB 813D[F0060000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2873 00005301 [23480000]          <1>
  2874 00005305 7415                <1>         je      short wmem_acc_err
  2875                              <1> 	;
  2876 00005307 8B35[786D0000]      <1>         mov     esi, [u.fofp] 
  2877                              <1> wmem_1:
  2878 0000530D E81F010000          <1> 	call	cpass
  2879                              <1> 		; jsr r0,cpass / get next character from users area of
  2880                              <1> 			     ; / core and put it in r1
  2881                              <1>         	; mov r1,-(sp) / put character on the stack
  2882                              <1> 	; 20/09/2013
  2883 00005312 74DF                <1> 	jz	short wret ; wmem_2  
  2884 00005314 8B1E                <1>         mov     ebx, [esi]
  2885                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2886 00005316 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2887                              <1> 		; inc *u.fofp / increment file offset to point to next
  2888                              <1> 			    ; / available location in file
  2889 00005318 8803                <1> 	mov	[ebx], al	
  2890                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2891                              <1> 			        ; / assigned to it
  2892 0000531A EBF1                <1> 	jmp	short wmem_1
  2893                              <1> 		; br wmem / continue
  2894                              <1> 	;1:
  2895                              <1> 	;jmp	error / ?
  2896                              <1> ;wmem_2:	
  2897                              <1> ;	; 20/09/2013
  2898                              <1> ;	pop	ax
  2899                              <1> ;	retn
  2900                              <1> 
  2901                              <1> wmem_acc_err:
  2902 0000531C C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2902 00005324 0000                <1>
  2903 00005326 E942DFFFFF          <1> 	jmp	error
  2904                              <1> 
  2905                              <1> ;wlpr:
  2906                              <1> 	; 12/06/2022
  2907                              <1> 	;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2908                              <1> 	;jmp 	error   ; ... Printing procedure will be located here ...
  2909                              <1> 		;/	jsr	r0,cpass
  2910                              <1> 		;/	cmp	r0,$'a
  2911                              <1> 		;/	blo	1f
  2912                              <1> 		;/	cmp	r1,$'z
  2913                              <1> 		;/	bhi	1f
  2914                              <1> 		;/	sub	$40,r1
  2915                              <1> 		;/1:
  2916                              <1> 		;/	jsr	r0,lptoc
  2917                              <1> 		;/	br	wlpr
  2918                              <1> 		; br rmem / continue
  2919                              <1> 
  2920                              <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - PRINTER BIOS (Functions)
  2921                              <1> 
  2922                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2923                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2924                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2925                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2926                              <1> 
  2927                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2928                              <1> 
  2929                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2930                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2931                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2932                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2933                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2934                              <1> RESERVED	equ 00000110b	; NOPS
  2935                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2936                              <1> 
  2937                              <1> ;----------------------------------------------------------------
  2938                              <1> ;								:
  2939                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2940                              <1> ;								:
  2941                              <1> ;   CX has count of bytes to be printed 			:
  2942                              <1> ;   ES:DI point to source buffer contains characters		:
  2943                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2944                              <1> ;								:
  2945                              <1> ;----------------------------------------------------------------
  2946                              <1> 
  2947                              <1> wlpr:
  2948                              <1> 	; 15/07/2022
  2949                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2
  2950                              <1> PRN$WRIT:
  2951                              <1> 	; INPUT:
  2952                              <1> 	;	[u.count] = count of characters to be printed
  2953                              <1> 	;	[u.base] = buffer address in user's memory space
  2954                              <1> 	;
  2955                              <1> 	;	(if ECX = 0, printer status will be returned)
  2956                              <1> 	
  2957                              <1> 	;xor	ebx, ebx
  2958                              <1> PRN$LOOP:
  2959 0000532B E801010000          <1> 	call	cpass		  ; Get a character into AL
  2960 00005330 7431                <1> 	jz	short pr_exit
  2961                              <1> 	;
  2962 00005332 B302                <1> 	mov	bl, 2  ; retry count
  2963                              <1> PRN$OUT:
  2964                              <1> 	; al = character which will be printed
  2965 00005334 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2966 00005336 E850000000          <1> 	call	PRNOP
  2967 0000533B 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2968                              <1> PrRetry:
  2969                              <1> 	; al = character
  2970 0000533D FECB                <1> 	dec	bl
  2971 0000533F 75F3                <1> 	jnz	short PRN$OUT
  2972                              <1> pr_err_exit:
  2973 00005341 0FB6C0              <1> 	movzx	eax, al
  2974 00005344 A3[D86D0000]        <1> 	mov	[u.error], eax
  2975 00005349 A3[646D0000]        <1> 	mov	[u.r0], eax ; error code in AL
  2976                              <1> 	;mov 	ebp, [u.sp]
  2977 0000534E 8B1D[5C6D0000]      <1> 	mov	ebx, [u.sp] ; 15/07/2022
  2978                              <1> 			; Kernel stack at the beginning of sys call
  2979 00005354 8B15[906D0000]      <1> 	mov	edx, [u.nread]
  2980 0000535A 4A                  <1> 	dec	edx ; last char failed
  2981                              <1> 	;mov	[ebp+20], edx ; count of printed characters in edx
  2982 0000535B 895314              <1> 	mov	[ebx+20], edx ; 15/07/2022
  2983 0000535E E90ADFFFFF          <1> 	jmp	error
  2984                              <1> pr_exit:
  2985 00005363 58                  <1> 	pop	eax ; inode number
  2986                              <1> 
  2987                              <1> 	;mov	eax, [u.nread]
  2988                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2989                              <1> 	;jmp	sysret
  2990 00005364 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2991                              <1> 
  2992                              <1> ; 12/06/2022
  2993                              <1> 
  2994                              <1> ;----------------------------------------------------------------
  2995                              <1> ;								:
  2996                              <1> ;		PRINTER STATUS ROUTINE				:
  2997                              <1> ;								:
  2998                              <1> ;----------------------------------------------------------------
  2999                              <1> ;
  3000                              <1> 	
  3001                              <1> lpr_stat:
  3002                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2					   
  3003                              <1> PRN$STAT:
  3004 00005365 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  3005 0000536A 750E                <1> 	jnz	short prn_stat_retn
  3006                              <1> 				  ; if error jump to error routine
  3007                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...    
  3008 0000536C B01F                <1> 	mov	al, ERR_PRN_PAPER
  3009 0000536E F6C420              <1> 	test	ah, NOPAPERSTATUS					   
  3010 00005371 7507                <1> 	jnz	short prn_stat_retn
  3011 00005373 F6C480              <1> 	test	ah, NOTBUSYSTATUS					   
  3012 00005376 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  3013 00005378 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  3014                              <1> prn_stat_retn:
  3015                              <1> 	; al = error code
  3016                              <1> 	; ah = status flags
  3017 0000537A A3[646D0000]        <1> 	mov	[u.r0], eax
  3018                              <1> 	;movzx	eax, al
  3019                              <1> 	;mov 	[u.error], eax
  3020 0000537F 58                  <1> 	pop	eax ; discard return address to syswrite
  3021 00005380 E908DFFFFF          <1> 	jmp	sysret
  3022                              <1> prn_stat_ok:
  3023 00005385 30C0                <1> 	xor	al, al ; 0
  3024 00005387 EBF1                <1> 	jmp	short prn_stat_retn
  3025                              <1> 
  3026                              <1> ;
  3027                              <1> ;   PRNSTAT	get printer status
  3028                              <1> ;   PRNOP	print a character
  3029                              <1> ;
  3030                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  3031                              <1> ; printer routines.  The routines share code which calls on the bios and
  3032                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  3033                              <1> ; only by the value put into AH before the ROM-BIOS call.
  3034                              <1> ;
  3035                              <1> ;   INPUT	if PRNOP then character in AL
  3036                              <1> ;
  3037                              <1> ;   OUTPUT	- AL holds error code
  3038                              <1> ;		- AH status byte from printer
  3039                              <1> ;		- flag NZ if error
  3040                              <1> 
  3041                              <1> PRNSTAT:						   
  3042 00005389 B402                <1> 	mov	ah, 2		  ; set command for get status 
  3043                              <1> 
  3044                              <1> PRNOP:
  3045                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2
  3046                              <1> 	;
  3047                              <1> 	; Print character (on paper)
  3048                              <1> 
  3049                              <1> 	; INPUT:
  3050                              <1> 	;	al = character to be printed
  3051                              <1> 	; OUTPUT:
  3052                              <1> 	;	zf = 1 -> ok
  3053                              <1> 	;	zf = 0 -> error code in AL
  3054                              <1> 
  3055 0000538B E8940B0000          <1> 	call	int17h	 ; call lpt bios
  3056                              <1> 	
  3057 00005390 F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?			   
  3058 00005393 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  3059                              <1> 
  3060                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  3061                              <1> 	; THE CONVERSE IS NOT TRUE.	   
  3062                              <1> 									   
  3063                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER	   
  3064 00005395 B01F                <1> 	mov	al, ERR_PRN_PAPER
  3065 00005397 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?		   
  3066 0000539A 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  3067                              <1> 	;mov	al, ERR_PRN_IO
  3068 0000539C FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR		   
  3069                              <1> PRNOP1:									   
  3070                              <1> 									   
  3071                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)	   
  3072                              <1> 									   
  3073 0000539E C3                  <1> 	retn			  ; RETURN WITH ERROR		   
  3074                              <1> 									   
  3075                              <1> ; THE BITS SAID NO ERROR.
  3076                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE. 								   
  3077                              <1> 									   
  3078                              <1> prnop_chk_nrdy:								   
  3079                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY		   
  3080 0000539F B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  3081                              <1> 	
  3082 000053A1 F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?		   
  3083                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  3084                              <1> PRNOP2: 
  3085 000053A4 C3                  <1> 	retn
  3086                              <1> 
  3087                              <1> 
  3088                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  3089                              <1> 
  3090                              <1> dskw: ; / write routine for non-special files
  3091                              <1> 	;
  3092                              <1> 	; 28/11/2021
  3093                              <1> 	; 25/07/2015
  3094                              <1> 	; 16/06/2015
  3095                              <1> 	; 09/06/2015
  3096                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  3097                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  3098                              <1> 
  3099                              <1> 	; 01/08/2013 (mkdir_w check)
  3100                              <1> 	;push	ax ; 26/04/2013
  3101                              <1> 	;	; mov (sp),r1 / get an i-node number from the stack into r1
  3102                              <1> 	; 28/11/2021
  3103 000053A5 50                  <1> 	push	eax
  3104                              <1> 	; AX = inode number
  3105 000053A6 E8DAF8FFFF          <1> 	call	iget
  3106                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  3107                              <1> 		            ; / read i-node 'r1' into i-node area of core
  3108 000053AB 8B1D[786D0000]      <1>         mov     ebx, [u.fofp] 
  3109 000053B1 8B13                <1> 	mov 	edx, [ebx]
  3110                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  3111                              <1> 			       ; / in the fsp entry for this file] in r2
  3112 000053B3 0315[8C6D0000]      <1> 	add 	edx, [u.count]	
  3113                              <1> 		; add u.count,r2 / no. of bytes to be written
  3114                              <1> 			       ; / + file offset is put in r2
  3115                              <1> 	;; 16/06/2015        
  3116                              <1> 	;cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  3117                              <1> 	;jna	short dskw_0
  3118                              <1> 	;mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  3119                              <1> 	;jmp	error
  3120                              <1> dskw_0:	
  3121                              <1> 	; 28/11/2021
  3122 000053B9 3B15[EC680000]      <1> 	cmp	edx, [i.size] ; 32 bit file size (runix v2 inode)
  3123                              <1> 	;cmp	dx, [i.size]
  3124                              <1> 	;	; cmp r2,i.size / is this greater than the present size of
  3125                              <1> 		              ; / the file?
  3126 000053BF 760B                <1> 	jna	short dskw_1
  3127                              <1> 		; blos 1f / no, branch
  3128 000053C1 8915[EC680000]      <1> 	mov	[i.size], edx ; 32 bit file size (runix v2 inode)
  3129                              <1> 	;mov	[i.size], dx
  3130                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3131                              <1> 			      ; / file offset + no. of data bytes
  3132 000053C7 E84AFAFFFF          <1> 	call	setimod
  3133                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3134                              <1> 		          ; / modified), stuff time of modification into
  3135                              <1> 	          	  ; / core image of i-node
  3136                              <1> dskw_1: ; 1:
  3137                              <1> 	; 28/11/2021
  3138                              <1> 	;call	mget
  3139 000053CC E834F5FFFF          <1> 	call	mget_w
  3140                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3141                              <1> 			    ; /	the next data byte
  3142                              <1> 	; eax = physical block/sector number
  3143 000053D1 8B1D[786D0000]      <1> 	mov     ebx, [u.fofp]
  3144 000053D7 8B13                <1> 	mov	edx, [ebx]
  3145 000053D9 81E2FF010000        <1> 	and	edx, 1FFh  
  3146                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3147 000053DF 750C                <1> 	jnz	short dskw_2
  3148                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3149                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3150 000053E1 813D[8C6D0000]0002- <1> 	cmp	dword [u.count], 512
  3150 000053E9 0000                <1>
  3151                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3152                              <1> 				  ; / an entire block? (i.e., no. of
  3153 000053EB 7305                <1> 	jnb	short dskw_3
  3154                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3155                              <1> 			; / Yes, branch. Don't have to read block
  3156                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3157                              <1>    		; / overwritten).
  3158 000053ED E89C060000          <1> 	call	dskrd
  3159                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3160                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3161                              <1> dskw_3: ; 3:
  3162                              <1> 	; EAX (r1) = block/sector number
  3163 000053F2 E8FB060000          <1> 	call	wslot
  3164                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3165                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3166 000053F7 803D[D66D0000]00    <1> 	cmp	byte [u.kcall], 0
  3167 000053FE 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3168                              <1> 	;
  3169 00005400 66833D[D06D0000]00  <1> 	cmp	word [u.pcount], 0
  3170 00005408 7705                <1> 	ja	short dskw_5
  3171                              <1> dskw_4:
  3172                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3173 0000540A E895FDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3174                              <1> dskw_5:
  3175                              <1> 	; eBX (r5) = system (I/O) buffer address
  3176 0000540F E87D000000          <1> 	call	sioreg
  3177                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3178                              <1> 			     ; / r1 = address of data, r2 points to location
  3179                              <1> 			     ; / in buffer in which to start writing data
  3180                              <1> 	; eSI = file (user data) offset
  3181                              <1> 	; eDI = sector (I/O) buffer offset
  3182                              <1> 	; eCX = byte count
  3183                              <1> 	;
  3184 00005414 F3A4                <1>   	rep	movsb
  3185                              <1> 		; movb (r1 )+,(r2)+ 
  3186                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3187                              <1> 		; dec r3 / decrement no. of bytes to be written
  3188                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3189                              <1> 	; 25/07/2015
  3190                              <1> 	; eax = remain bytes in buffer
  3191                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3192 00005416 09C0                <1> 	or	eax, eax
  3193 00005418 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3194                              <1> dskw_6:
  3195 0000541A E8E0060000          <1> 	call	dskwr
  3196                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3197 0000541F 833D[8C6D0000]00    <1>         cmp     dword [u.count], 0
  3198                              <1> 		; tst u.count / any more data to write?
  3199 00005426 77A4                <1> 	ja	short dskw_1
  3200                              <1> 		; bne 1b / yes, branch
  3201                              <1> 	; 03/08/2013
  3202 00005428 C605[D66D0000]00    <1> 	mov	byte [u.kcall], 0
  3203                              <1> 	; 20/09/2013 (;;)
  3204                              <1> 	;pop	ax
  3205                              <1> 	; 28/11/2021
  3206 0000542F 58                  <1> 	pop	eax  
  3207 00005430 C3                  <1> 	retn
  3208                              <1> 	;;jmp 	short dskw_ret 
  3209                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3210                              <1> 
  3211                              <1> 	; 24/12/2021
  3212                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3213                              <1> cpass: ; / get next character from user area of core and put it in r1
  3214                              <1> 	; 18/10/2015
  3215                              <1> 	; 10/10/2015
  3216                              <1> 	; 10/07/2015
  3217                              <1> 	; 02/07/2015
  3218                              <1> 	; 01/07/2015
  3219                              <1> 	; 24/06/2015
  3220                              <1> 	; 08/06/2015
  3221                              <1> 	; 04/06/2015
  3222                              <1> 	; 20/05/2015
  3223                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3224                              <1> 	;
  3225                              <1> 	; INPUTS -> 
  3226                              <1> 	;     [u.base] = virtual address in user area
  3227                              <1> 	;     [u.count] = byte count (max.)
  3228                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3229                              <1> 	; OUTPUTS -> 
  3230                              <1> 	;     AL = the character which is pointed by [u.base]
  3231                              <1> 	;     zf = 1 -> transfer count has been completed	
  3232                              <1>         ;
  3233                              <1> 	; ((Modified registers: EAX, EDX, ECX))
  3234                              <1> 	;
  3235                              <1> 	;
  3236 00005431 833D[8C6D0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3237                              <1> 		; tst u.count / have all the characters been transferred
  3238                              <1> 			    ; / (i.e., u.count, # of chars. left
  3239 00005438 763F                <1> 	jna	short cpass_3
  3240                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3241 0000543A FF0D[8C6D0000]      <1> 	dec	dword [u.count]
  3242                              <1> 		; dec u.count / no, decrement u.count
  3243                              <1>         ; 19/05/2015 
  3244                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3245                              <1> 	;		      to physical address
  3246 00005440 66833D[D06D0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3247                              <1> 			     ; 1-4095 --> use previous physical base address
  3248                              <1> 			     ; in [u.pbase]
  3249 00005448 770E                <1> 	ja	short cpass_1
  3250                              <1> 	; 02/07/2015
  3251 0000544A 833D[C86D0000]00    <1> 	cmp	dword [u.ppgdir], 0  ; is the caller os kernel
  3252 00005451 7427                <1> 	je	short cpass_k 	; (sysexec, '/etc/init') ? 
  3253                              <1> 	; 08/06/2015 - 10/07/2015
  3254 00005453 E84CFDFFFF          <1> 	call	trans_addr_r
  3255                              <1> cpass_1:
  3256                              <1> 	; 02/07/2015
  3257                              <1> 	; 24/06/2015
  3258 00005458 66FF0D[D06D0000]    <1> 	dec	word [u.pcount]
  3259                              <1> cpass_2: 
  3260                              <1> 	; 10/10/2015
  3261                              <1> 	; 02/07/2015
  3262 0000545F 8B15[CC6D0000]      <1> 	mov	edx, [u.pbase]
  3263 00005465 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3264                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3265                              <1> 				; / by u.base and put it in r1
  3266 00005467 FF05[906D0000]      <1> 	inc	dword [u.nread]
  3267                              <1> 		; inc u.nread / increment no. of bytes transferred
  3268 0000546D FF05[886D0000]      <1> 	inc	dword [u.base]
  3269                              <1> 		; inc u.base / increment the buffer address to point to the
  3270                              <1> 			   ; / next byte
  3271 00005473 FF05[CC6D0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3272                              <1> cpass_3:
  3273 00005479 C3                  <1> 	retn
  3274                              <1> 		; rts	r0 / next byte
  3275                              <1> 	; 1: 
  3276                              <1> 		; mov (sp)+,r0 
  3277                              <1> 		         ; / put return address of calling routine into r0
  3278                              <1> 		; mov (sp)+,r1 / i-number in r1
  3279                              <1> 		; rts r0 / non-local return
  3280                              <1> cpass_k:
  3281                              <1> 	; 02/07/2015
  3282                              <1> 	; The caller is os kernel 
  3283                              <1> 	; (get sysexec arguments from kernel's memory space)
  3284                              <1> 	;
  3285 0000547A 8B1D[886D0000]      <1> 	mov	ebx, [u.base]
  3286 00005480 66C705[D06D0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3286 00005488 10                  <1>
  3287 00005489 891D[CC6D0000]      <1> 	mov	[u.pbase], ebx
  3288 0000548F EBCE                <1> 	jmp	short cpass_2
  3289                              <1> 	
  3290                              <1> sioreg: 
  3291                              <1> 	; 25/07/2015
  3292                              <1> 	; 18/07/2015
  3293                              <1> 	; 02/07/2015
  3294                              <1> 	; 17/06/2015
  3295                              <1> 	; 09/06/2015
  3296                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3297                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3298                              <1> 	;
  3299                              <1> 	; INPUTS -> 
  3300                              <1> 	;     eBX = system buffer (data) address (r5)
  3301                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3302                              <1> 	;     [u.base] = virtual address of the user buffer
  3303                              <1> 	;     [u.pbase] = physical address of the user buffer
  3304                              <1> 	;     [u.count] = byte count
  3305                              <1> 	;     [u.pcount] = byte count within page frame 			
  3306                              <1> 	; OUTPUTS -> 
  3307                              <1> 	;     eSI = user data offset (r1)
  3308                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3309                              <1> 	;     eCX = byte count (r3)
  3310                              <1> 	;     EAX = remain bytes after byte count within page frame
  3311                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3312                              <1>         ;
  3313                              <1> 	; ((Modified registers:  EDX))
  3314                              <1>  
  3315 00005491 8B35[786D0000]      <1>         mov     esi, [u.fofp]
  3316 00005497 8B3E                <1>         mov     edi, [esi]
  3317                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3318 00005499 89F9                <1> 	mov	ecx, edi
  3319                              <1> 		; mov r2,r3 / and also to r3
  3320 0000549B 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3321                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3322 000054A1 81E7FF010000        <1> 	and	edi, 1FFh
  3323                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3324 000054A7 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3325                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3326                              <1> 			  ; / where data is to be placed
  3327                              <1>                 ; mov u.base,r1 / address of data is in r1
  3328 000054A9 F7D9                <1> 	neg	ecx
  3329                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3330                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3331 000054AB 3B0D[8C6D0000]      <1> 	cmp	ecx, [u.count]
  3332                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3333                              <1> 			       ; / to be written to the file
  3334 000054B1 7606                <1> 	jna	short sioreg_0
  3335                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3336                              <1> 			 ; / in the file block as the number to be written
  3337 000054B3 8B0D[8C6D0000]      <1> 	mov	ecx, [u.count]
  3338                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3339                              <1> 			       ; / bytes as the number to be written
  3340                              <1> sioreg_0:
  3341                              <1> 	; 17/06/2015
  3342 000054B9 803D[D66D0000]00    <1> 	cmp	byte [u.kcall], 0 
  3343 000054C0 7613                <1> 	jna	short sioreg_1
  3344                              <1> 	; 25/07/2015
  3345                              <1> 	 ; the caller is 'mkdir' or 'namei'
  3346 000054C2 A1[886D0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3347 000054C7 A3[CC6D0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3348 000054CC 66890D[D06D0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3349 000054D3 EB0B                <1> 	jmp	short sioreg_2
  3350                              <1> sioreg_1:
  3351                              <1> 	; 25/07/2015
  3352                              <1> 	; 18/07/2015
  3353                              <1> 	; 09/06/2015 
  3354 000054D5 0FB715[D06D0000]    <1> 	movzx	edx, word [u.pcount]
  3355                              <1> 		; ecx and [u.pcount] are always > 0, here
  3356 000054DC 39D1                <1> 	cmp	ecx, edx	
  3357 000054DE 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3358                              <1> sioreg_2: ; 2:
  3359 000054E0 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3360                              <1> sioreg_3:
  3361 000054E2 010D[906D0000]      <1> 	add 	[u.nread], ecx
  3362                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3363                              <1> 			         ; / during write is put into u.nread
  3364 000054E8 290D[8C6D0000]      <1> 	sub 	[u.count], ecx
  3365                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3366                              <1> 			       ; / must be written or read
  3367 000054EE 010D[886D0000]      <1> 	add 	[u.base], ecx
  3368                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3369                              <1> 			      ; / data bytes
  3370 000054F4 010E                <1>         add 	[esi], ecx 
  3371                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3372                              <1> 			       ; / + old file offset
  3373                              <1> 	; 25/07/2015
  3374 000054F6 8B35[CC6D0000]      <1> 	mov	esi, [u.pbase]
  3375 000054FC 66290D[D06D0000]    <1> 	sub	[u.pcount], cx
  3376 00005503 010D[CC6D0000]      <1> 	add	[u.pbase], ecx
  3377 00005509 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 0000550A 89C8                <1> 	mov	eax, ecx
  3385 0000550C 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3386 0000550E 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3387 00005510 EBD0                <1> 	jmp	short sioreg_3
  3388                              <1> 
  3389                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  3390                              <1> is_regular_file:
  3391                              <1> 	; check if it is a regular file or device file inode
  3392                              <1> 	;
  3393                              <1> 	; INPUT:
  3394                              <1> 	;	current inode
  3395                              <1> 	; OUTPUT:
  3396                              <1> 	;	cf = 0 and zf = 1 -> regular file
  3397                              <1> 	;	cf = 0 and zf = 0 -> device file
  3398                              <1> 	;	cf = 1 -> invalid file (jump to 'error')
  3399                              <1> 	;
  3400                              <1> 	; Modified registers: ecx (cl)
  3401                              <1> 
  3402                              <1> 	; 28/11/2021
  3403 00005512 8A0D[E5680000]      <1> 	mov	cl, [i.flgs+1]
  3404 00005518 F6C180              <1> 	test	cl, 80h		; regular file ?
  3405 0000551B 7514                <1> 	jnz	short isregf_1  ; yes 
  3406 0000551D 80E120              <1> 	and	cl, 20h 	; device file ?
  3407 00005520 7511                <1> 	jnz	short isregf_2  ; yes 
  3408                              <1> 
  3409                              <1> 	; 28/11/2021
  3410                              <1> 	; invalid inode/file type !
  3411 00005522 C705[D86D0000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  3411 0000552A 0000                <1>
  3412                              <1> 	;stc
  3413                              <1> 	;retn
  3414 0000552C E93CDDFFFF          <1> 	jmp	error
  3415                              <1> isregf_1:
  3416 00005531 30C9                <1> 	xor	cl, cl  ; cl = 0
  3417                              <1> 	; zf = 1
  3418                              <1> 	;retn
  3419                              <1> isregf_2:
  3420                              <1> 	; zf = 0
  3421                              <1> 	; cl = 20h
  3422 00005533 C3                  <1> 	retn	
  2093                                  %include 'u7.s'      ; 18/04/2015
  2094                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2095                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2096                              <1> ; ****************************************************************************
  2097                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - SYS7.INC
  2098                              <1> ; Last Modification: 12/06/2022
  2099                              <1> ; ----------------------------------------------------------------------------
  2100                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2101                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2102                              <1> ;
  2103                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2104                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2105                              <1> ; <Bell Laboratories (17/3/1972)>
  2106                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2107                              <1> ;
  2108                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2109                              <1> ;
  2110                              <1> ; ****************************************************************************
  2111                              <1> 
  2112                              <1> sysmount: ; / mount file system; args special; name
  2113                              <1> 	; 15/05/2022
  2114                              <1> 	; 09/05/2022
  2115                              <1> 	;	 (Retro UNIX 386 v1.2, Kernel v0.2.2.1)
  2116                              <1> 	; 08/02/2022
  2117                              <1> 	; 07/02/2022
  2118                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2119                              <1> 	; 14/11/2015
  2120                              <1> 	; 24/10/2015
  2121                              <1> 	; 13/10/2015
  2122                              <1> 	; 10/07/2015
  2123                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2124                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2125                              <1> 	;
  2126                              <1> 	; 'sysmount' anounces to the system that a removable 
  2127                              <1> 	; file system has been mounted on a special file.
  2128                              <1> 	; The device number of the special file is obtained via
  2129                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2130                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2131                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2132                              <1> 	; to read file system into core, i.e. the first block on the
  2133                              <1> 	; mountable file system is read in. This block is super block
  2134                              <1> 	; for the file system. This call is super user restricted.	
  2135                              <1> 	;
  2136                              <1> 	; Calling sequence:
  2137                              <1> 	;	sysmount; special; name
  2138                              <1> 	; Arguments:
  2139                              <1> 	;	special - pointer to name of special file (device)
  2140                              <1> 	;	name -  pointer to name of the root directory of the
  2141                              <1> 	;		newly mounted file system. 'name' should 
  2142                              <1> 	;		always be a directory.
  2143                              <1> 	; Inputs: - 
  2144                              <1> 	; Outputs: -
  2145                              <1> 	; ...............................................................
  2146                              <1> 	;				
  2147                              <1> 	; Retro UNIX 8086 v1 modification: 
  2148                              <1> 	;       'sysmount' system call has two arguments; so,
  2149                              <1> 	;	* 1st argument, special is pointed to by BX register
  2150                              <1> 	;	* 2nd argument, name is in CX register
  2151                              <1> 	;
  2152                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2153                              <1> 	;	       already modified for IBM PC compatibility and 
  2154                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2155                              <1> 	
  2156                              <1> 	;call	arg2
  2157                              <1> 		; jsr r0,arg2 / get arguments special and name
  2158 00005534 891D[806D0000]      <1> 	mov	[u.namep], ebx
  2159                              <1> 	; 07/02/2022
  2160                              <1> 	;push	ecx ; directory name
  2161                              <1> 	;cmp	dword [mnti], 0 ; 11/01/2022 (32 bit inode number)
  2162 0000553A 66833D[4A6D0000]00  <1> 	cmp	word [mnti], 0
  2163                              <1> 		; tst mnti / is the i-number of the cross device file
  2164                              <1> 			 ; / zero?
  2165                              <1> 	;;ja	error
  2166                              <1>         	; bne errora / no, error
  2167                              <1> 	;ja	sysmnt_err0
  2168                              <1> 	; 11/01/2022
  2169 00005542 7605                <1> 	jna	short sysmnt_0 ; 12/01/2022
  2170                              <1> sysmnt_0_err:
  2171 00005544 E993010000          <1> 	jmp	sysmnt_err0
  2172                              <1> sysmnt_0:
  2173                              <1> 	; 07/02/2022
  2174 00005549 51                  <1> 	push	ecx ; directory name
  2175 0000554A E875010000          <1> 	call	getspl
  2176                              <1> 		; jsr r0,getspl / get special files device number in r1
  2177                              <1> 	; 07/02/2022
  2178 0000554F 8F05[806D0000]      <1> 	pop	dword [u.namep] ; directory name
  2179                              <1> 
  2180                              <1> 	; 09/05/2022 - Retro UNIX v1.2 (Kernel v0.2.2.1)
  2181                              <1> 	; (root fs/device must not be mounted again)
  2182 00005555 3A05[426D0000]      <1> 	cmp	al, [rdev]
  2183                              <1> 	;je	sysmnt_err0
  2184 0000555B 74E7                <1> 	je	short sysmnt_0_err ; permission denied error
  2185                              <1> 
  2186                              <1> 	; 13/10/2015
  2187                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2188                              <1>         ; 11/01/2022
  2189 0000555D 29DB                <1> 	sub	ebx, ebx
  2190 0000555F 88C3                <1> 	mov	bl, al
  2191 00005561 F683[6E630000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2192 00005568 750F                <1> 	jnz	short sysmnt_1
  2193                              <1> sysmnt_err1:
  2194 0000556A C705[D86D0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2194 00005572 0000                <1>
  2195 00005574 E9F4DCFFFF          <1> 	jmp	error
  2196                              <1> sysmnt_1:
  2197                              <1> 	; 07/02/2022
  2198                              <1> 	;pop	dword [u.namep]
  2199                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2200                              <1> 				  ; / on the device
  2201                              <1> 	; 14/11/2015
  2202 00005579 53                  <1> 	push	ebx ; 13/10/2015
  2203                              <1> 		; mov r1,-(sp) / save the device number
  2204                              <1>         ;
  2205 0000557A E806ECFFFF          <1> 	call	namei
  2206                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2207                              <1> 		       ; ax = 0 -> file not found 	
  2208                              <1> 	;jz	error
  2209                              <1> 	;jc	error
  2210                              <1> 		; jsr r0,namei / get the i-number of the file
  2211                              <1>                	; br errora
  2212 0000557F 730F                <1> 	jnc	short sysmnt_2
  2213                              <1> sysmnt_err2:
  2214 00005581 C705[D86D0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2214 00005589 0000                <1>
  2215 0000558B E9DDDCFFFF          <1> 	jmp	error
  2216                              <1> sysmnt_2:
  2217                              <1> 	; 11/01/2022
  2218 00005590 A3[4A6D0000]        <1> 	mov	[mnti], eax ; 32 bit inode number (<= 65535)	
  2219                              <1> 	;mov	[mnti], ax
  2220                              <1>         	; mov r1,mnti / put it in mnti
  2221                              <1> 
  2222                              <1> 	; 15/05/2022
  2223                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2224 00005595 A1[3C6D0000]        <1> 	mov	eax, [ii]
  2225 0000559A A3[4E6D0000]        <1> 	mov	[mntp], eax ; parent dir inumber of [mnti]
  2226                              <1> 
  2227                              <1> 	; 11/01/2022
  2228 0000559F BB[14700000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2229                              <1> sysmnt_3: ;1:
  2230                              <1>         ;cmp	byte [ebx+1], 0
  2231                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2232                              <1> 			   ; / dismountable device set?
  2233                              <1>         ;jna	short sysmnt_4		
  2234                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2235                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2236                              <1> 	;jmp	short sysmnt_3
  2237                              <1> sysmnt_4:   
  2238 000055A4 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2239 000055A5 A2[436D0000]        <1> 	mov	[mdev], al
  2240                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2241 000055AA 8803                <1> 	mov	[ebx], al
  2242                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2243                              <1> 			      ; / of the I/O queue entry
  2244                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2245                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2246 000055AC 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2247                              <1> 		; bis $2000,sb1 / set the read bit
  2248                              <1> 
  2249                              <1> 	; 09/05/2022
  2250 000055B1 31FF                <1> 	xor	edi, edi
  2251 000055B3 897B04              <1> 	mov	dword [ebx+4], edi ; 0 ; physical block number = 0
  2252                              <1> 
  2253                              <1> 	; 09/05/2022
  2254                              <1> 	; Retro UNIX v2 Hard Disk FS recognition.
  2255                              <1> 	;
  2256 000055B6 3C02                <1> 	cmp	al, 2 ; fd0 = 0, fd1 = 1, hd0 = 2, hd1 = 3
  2257 000055B8 7217                <1> 	jb	short sysmnt_8
  2258                              <1> 
  2259                              <1> 	; hard disk, read masterboot sector/block at first 
  2260 000055BA E80F060000          <1> 	call 	diskio
  2261 000055BF 721A                <1> 	jc	short sysmnt_9 ; disk read error !
  2262                              <1> sysmnt_6:
  2263                              <1>   	; return start sector address of
  2264                              <1> 	; retro unix v2 partition in esi
  2265 000055C1 8D7308              <1> 	lea	esi, [ebx+8] ; (mbr buffer data address)
  2266 000055C4 E86FDBFFFF          <1> 	call	runix_p_bs
  2267 000055C9 7206                <1> 	jc	short sysmnt_8 ; runix partition not found
  2268                              <1> 			       ; try to read superblock on
  2269                              <1> 			       ; physical sector 1	 
  2270                              <1> 	; eax = start sector/block
  2271 000055CB 894304              <1> 	mov	dword [ebx+4], eax ; (boot sector address)
  2272                              <1> 	; esi = partition table entry + 4
  2273 000055CE 8B7E08              <1> 	mov	edi, [esi+ptSectors-ptFileSystemID]
  2274                              <1> 	; edi = partition size in sectors
  2275                              <1> sysmnt_8:
  2276                              <1> 	; Retro UNIX 386 v1 modification : 
  2277                              <1> 	;	32 bit block number at buffer header offset 4
  2278                              <1> 	; 09/05/2022
  2279                              <1> 	;mov	dword [ebx+4], 1 ; physical block number = 1
  2280 000055D1 FF4304              <1> 	inc	dword [ebx+4] ; +1 ; superblock address
  2281 000055D4 E8F5050000          <1> 	call 	diskio
  2282 000055D9 7345                <1> 	jnc	short sysmnt_5
  2283                              <1> sysmnt_9:
  2284 000055DB 31C0                <1> 	xor 	eax, eax
  2285 000055DD 66A3[4A6D0000]      <1> 	mov	[mnti], ax ; 0
  2286 000055E3 A2[436D0000]        <1> 	mov	[mdev], al ; 0
  2287                              <1> 	;mov	[cdev], al ; 0
  2288                              <1> 	; 08/02/2022
  2289 000055E8 803D[D76D0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2290 000055EF 7508                <1> 	jne	short sysmnt_err3
  2291                              <1> 	; yes, clear [u.brwdev] for next check
  2292                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2293 000055F1 FE05[D76D0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2294 000055F7 EB0A                <1> 	jmp	short sysmnt_err4
  2295                              <1> sysmnt_err3:	; 08/02/2022
  2296                              <1> 	; no, set [u.error] to disk read error
  2297 000055F9 C705[D86D0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2297 00005601 0000                <1>
  2298                              <1> sysmnt_err4:
  2299                              <1> 	; 08/02/2022
  2300                              <1> 	; 14/11/2015
  2301 00005603 FEC8                <1> 	dec 	al
  2302 00005605 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2303 00005607 FEC0                <1> 	inc	al
  2304 00005609 48                  <1> 	dec	eax
  2305 0000560A 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2306 0000560D E95BDCFFFF          <1> 	jmp	error
  2307                              <1> sysmnt_invd:
  2308                              <1> 	; 08/02/2022
  2309 00005612 C705[D86D0000]1C00- <1> 	mov	dword [u.error], ERR_INV_FS ; 28
  2309 0000561A 0000                <1>
  2310                              <1> 				 ;'invalid fs/superblock !' error
  2311 0000561C 30C0                <1> 	xor	al, al ; 0
  2312 0000561E EBE3                <1> 	jmp	short sysmnt_err4
  2313                              <1> 
  2314                              <1> sysmnt_5:
  2315                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.1)
  2316                              <1> 	; Retro UNIX v2 Hard Disk FS recognition.
  2317                              <1> 	; edi = 0 -> diskette or 'not a runix v2 hdfs partition'
  2318                              <1> 	; edi > 0 -> retro unix v2 hdfs partition (volume) size
  2319                              <1> 	;	     in sectors
  2320                              <1> 
  2321 00005620 21FF                <1> 	and	edi, edi
  2322 00005622 740D                <1> 	jz	short sysmnt_10
  2323                              <1> 
  2324 00005624 8B530C              <1> 	mov	edx, [ebx+12] ; SB.BootSectAddr (Hidden Sectors)
  2325 00005627 42                  <1> 	inc	edx ; +1 
  2326 00005628 3B5304              <1> 	cmp	edx, [ebx+4]  ; superblock (disk) address
  2327 0000562B 75E5                <1> 	jne	short sysmnt_invd  ; invalid file system !
  2328                              <1> 
  2329 0000562D 89F9                <1> 	mov	ecx, edi ; volume size (from partition table entry)
  2330 0000562F EB0C                <1> 	jmp	short sysmnt_11 ; bypass disk size comparison
  2331                              <1> 
  2332                              <1> sysmnt_10:
  2333                              <1> 	; 08/02/2022
  2334                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1 BugFix)
  2335                              <1> 	;  v1.2 Note: This code will be changed for hard disk partitions
  2336                              <1> 	;	    ! (for now, rufs v2 floppy disks can be mounted) !		
  2337                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2338                              <1> 	; (Following check is needed to prevent mounting an
  2339                              <1> 	; invalid file system (invalid super block).
  2340                              <1> 	; 
  2341 00005631 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2342 00005634 C0E002              <1> 	shl	al, 2 ; 4*index
  2343 00005637 8B88[52630000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2344                              <1> 	;shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2345                              <1> 	; ecx = number of free map bytes (required)
  2346                              <1> 	;;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2347                              <1> 	;movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2348                              <1> 	; edx = number of free blocks map bytes
  2349                              <1> 	;;shl	edx, 3 ; convert free map bytes to free map bits
  2350                              <1> 	;cmp	ecx, edx ; compare free map bits and volume size
  2351                              <1> 	;		 ; (in sectors), if they are not equal
  2352                              <1> 	;		 ; the disk to be mounted is an...
  2353                              <1> 	;jne	short sysmnt_invd ; invalid disk !
  2354                              <1> 	;		 ; (which has not got a valid super block)
  2355                              <1> sysmnt_11:	
  2356                              <1> 	; 07/02/2022
  2357                              <1> 	;xor	al, al ; 08/02/2022
  2358                              <1> 	; 11/01/2022
  2359                              <1> 	; Retro UNIX 386 v2 superblock (offset 8, volume size)
  2360 0000563D 8B5310              <1> 	mov	edx, [ebx+16] ; SB.VolumeSize (in sectors)
  2361 00005640 39D1                <1> 	cmp	ecx, edx ; compare SB.VolumeSize and Disk volume size
  2362                              <1> 			 ; (in sectors), if they are not equal
  2363                              <1> 			 ; the disk to be mounted is an...	
  2364 00005642 75CE                <1> 	jne	short sysmnt_invd ; invalid disk !
  2365                              <1> 			 ; (which has not got a valid shuper block)
  2366                              <1> 	;
  2367 00005644 C6430100            <1> 	mov	byte [ebx+1], 0
  2368                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2369                              <1> ;sysmnt_6: ;1:
  2370                              <1> 	;;cmp	byte [sb1+1], 0
  2371                              <1> 		; tstb sb1+1 / done reading?
  2372                              <1>    	;;jna	sysret
  2373                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2374                              <1> 	;;jmp	short sysmnt_6
  2375                              <1> 		;bne 1b / no, wait
  2376                              <1>         	;br sysreta / yes
  2377 00005648 E940DCFFFF          <1> 	jmp	sysret
  2378                              <1> 
  2379                              <1> sysumount: ; / special dismount file system
  2380                              <1> 	; 15/05/2022
  2381                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.2, Kernel v0.2.2.1)
  2382                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2383                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2384                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2385                              <1> 	;
  2386                              <1> 	; 04/11/2013
  2387                              <1> 	; 09/07/2013
  2388                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2389                              <1> 	; indicated as an argument is no longer contain a removable
  2390                              <1> 	; file system. 'getspl' gets the device number of the special
  2391                              <1> 	; file. If no file system was mounted on that device an error
  2392                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2393                              <1> 	; to 'sysret'.
  2394                              <1> 	;
  2395                              <1> 	; Calling sequence:
  2396                              <1> 	;	sysmount; special
  2397                              <1> 	; Arguments:
  2398                              <1> 	;	special - special file to dismount (device)
  2399                              <1> 	;
  2400                              <1> 	; Inputs: - 
  2401                              <1> 	; Outputs: -
  2402                              <1> 	; ...............................................................
  2403                              <1> 	;				
  2404                              <1> 	; Retro UNIX 8086 v1 modification: 
  2405                              <1> 	;       'sysumount' system call has one argument; so,
  2406                              <1> 	;	* Single argument, special is pointed to by BX register
  2407                              <1> 	;
  2408                              <1> 	
  2409                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2410                              <1> 	;call	arg
  2411                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2412 0000564D 891D[806D0000]      <1>         mov	[u.namep], ebx
  2413 00005653 E86C000000          <1> 	call	getspl
  2414                              <1> 		; jsr r0,getspl / get the device number in r1
  2415                              <1> 	;;;
  2416                              <1> 	; 09/05/2022 - Erdogan Tan
  2417                              <1> 	; (I have added [mnti] check because
  2418                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2419                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2420                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2421                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2422 00005658 66833D[4A6D0000]00  <1> 	cmp	word [mnti], 0
  2423 00005660 767A                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2424                              <1> 	;;;	
  2425                              <1> 
  2426 00005662 3A05[436D0000]      <1> 	cmp	al, [mdev]
  2427                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2428 00005668 7572                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2429                              <1> 	;jne	error
  2430                              <1>         	; bne errora / no error
  2431 0000566A 30C0                <1> 	xor	al, al ; ah = 0
  2432                              <1> 	; (eax = 0) ; 11/01/2022
  2433                              <1> sysumnt_0: ;1:
  2434                              <1>      	; 11/01/2022
  2435                              <1> 	;cmp 	[sb1+1], al ; 0
  2436                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2437                              <1> 	;		   ; / (inhibit bit set)?
  2438                              <1> 	;jna	short sysumnt_1		
  2439                              <1> 	;	; bne 1b / yes, wait
  2440                              <1> 	;call	idle ; (wait for hardware interrupt)
  2441                              <1> 	;jmp	short sysumnt_0
  2442                              <1> sysumnt_1:
  2443                              <1> 	; 15/05/2022
  2444                              <1> 	; change user's current directory to mounting directory
  2445                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2446 0000566C 3805[6C6D0000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2447 00005672 7641                <1> 	jna	short sysumnt_4
  2448                              <1> 	;;;
  2449                              <1> 	; 15/05/2022
  2450                              <1> 	; It is needed to change the parent process's current
  2451                              <1> 	; directory because shell runs (/etc/umount) 
  2452                              <1> 	; as child process.
  2453 00005674 31DB                <1> 	xor	ebx, ebx 
  2454 00005676 8A1D[B56D0000]      <1> 	mov	bl, [u.uno]
  2455 0000567C D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2456 0000567E 81C3[42690000]      <1> 	add	ebx, p.ppid-2
  2457 00005684 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2458 00005687 BE[24690000]        <1> 	mov	esi, p.pid
  2459 0000568C 29C9                <1> 	sub	ecx, ecx
  2460 0000568E B110                <1> 	mov	cl, nproc ; 16  
  2461                              <1> sysumnt_2:	
  2462 00005690 66AD                <1> 	lodsw
  2463 00005692 6639D0              <1> 	cmp	ax, dx
  2464 00005695 7402                <1> 	je	short sysumnt_3
  2465 00005697 E2F7                <1> 	loop	sysumnt_2
  2466                              <1> sysumnt_3:
  2467 00005699 31C0                <1> 	xor	eax, eax
  2468 0000569B 81EE[24690000]      <1> 	sub	esi, p.pid
  2469 000056A1 D1E6                <1> 	shl	esi, 1
  2470 000056A3 8B9E[90690000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2471                              <1> 	; ebx points to user (u) structure in upage
  2472 000056A9 8B15[4A6D0000]      <1> 	mov	edx, [mnti] ; * (32 bit inumber but < 65536)
  2473                              <1> 	;mov	[u.cdir], dx
  2474                              <1> 	;mov	[u.cdrv], al ; 0
  2475 000056AF 89530C              <1> 	mov	[ebx+u.cdir-user], edx 
  2476                              <1> 			    ; * (32 bit inumber but < 65536)
  2477 000056B2 884310              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2478                              <1> 	;;;
  2479                              <1> sysumnt_4:
  2480 000056B5 A2[436D0000]        <1> 	mov	[mdev], al ; 0
  2481                              <1> 	     	; clr mntd / no, clear these
  2482 000056BA A3[4A6D0000]        <1>    	mov	[mnti], eax ; 11/01/2022 (eax = 0)
  2483                              <1> 	;mov	[mnti], ax ; 0
  2484                              <1>         	; clr mnti
  2485                              <1> 
  2486                              <1> 	;; 15/05/2022
  2487                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2488                              <1> 	;mov	eax, edx  ; [u.cdir]
  2489                              <1> 	;call	iget
  2490                              <1> 
  2491 000056BF E9C9DBFFFF          <1>         jmp	sysret
  2492                              <1> 		; br sysreta / return
  2493                              <1> 
  2494                              <1> 	; 11/01/2022 - Retro UNIX 386 v1.2
  2495                              <1> 	;	(runix v2 fs inode numbers)
  2496                              <1> getspl: ; / get device number from a special file name
  2497 000056C4 E8BCEAFFFF          <1> 	call	namei
  2498                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2499                              <1> 		       ; ax = 0 -> file not found 	
  2500                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2501                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2502 000056C9 7305                <1> 	jnc	short getspl_0
  2503 000056CB E9B1FEFFFF          <1> 	jmp	sysmnt_err2
  2504                              <1> getspl_0:
  2505                              <1> 	;jz	error
  2506                              <1> 	;jc	error
  2507                              <1> 		; jsr r0,namei / get the i-number of the special file
  2508                              <1>                 ; br errora / no such file
  2509                              <1>         ; 11/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode numbers)
  2510 000056D0 6683E80A            <1> 	sub	ax, 10 ; fd0 inode number = 10, hd3 inode number = 15
  2511                              <1> 		      ;	i-number-10, 0 = fd0, 5 = hd3 
  2512                              <1> 	;sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2513                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2514                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2515 000056D4 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2516                              <1> 	;jc	error
  2517                              <1> 		; ble errora / less than 0?  yes, error
  2518 000056D6 6683F805            <1>         cmp	ax, 5 ; 5 = hd3
  2519                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2520                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2521                              <1> 	;;ja	error
  2522                              <1> 		; bgt errora / yes, error
  2523                              <1> 	; 11/01/2022
  2524 000056DA 760F                <1> 	jna	short getspl_retn
  2525                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2526                              <1> ;iopen_retn:
  2527                              <1> ;	retn
  2528                              <1> 		; rts    r0 / return with device number in r1
  2529                              <1> sysmnt_err0:
  2530 000056DC C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2530 000056E4 0000                <1>
  2531 000056E6 E982DBFFFF          <1> 	jmp	error
  2532                              <1> 
  2533                              <1> getspl_retn:
  2534                              <1> 	; 11/01/2022
  2535                              <1> 	; eax = Retro UNIX 386 v1 device number (0 to 5)
  2536                              <1> iopen_retn:
  2537 000056EB C3                  <1> 	retn
  2538                              <1> 
  2539                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2 
  2540                              <1> 	;			(Printer initialization)
  2541                              <1> 	; 11/02/2022
  2542                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2543                              <1> iopen:
  2544                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2545                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  2546                              <1> 	; 19/05/2015
  2547                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2548                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2549                              <1> 	;
  2550                              <1> 	; open file whose i-number is in r1
  2551                              <1> 	; 
  2552                              <1> 	; INPUTS ->
  2553                              <1> 	;    r1 - inode number
  2554                              <1> 	; OUTPUTS ->
  2555                              <1> 	;    file's inode in core	
  2556                              <1> 	;    r1 - inode number (positive)
  2557                              <1> 	;
  2558                              <1> 	; ((AX = R1))
  2559                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2560                              <1> 	;        
  2561                              <1> ; / open file whose i-number is in r1
  2562                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2563                              <1> ;		; tst r1 / write or read access?
  2564                              <1> ;       jnz	short iopen_2
  2565                              <1> ;		; blt 2f / write, go to 2f
  2566                              <1> ;	mov	dl, 2 ; read access
  2567                              <1> ;	call	access
  2568                              <1> ;       	; jsr r0,access; 2 
  2569                              <1> ;	; / get inode into core with read access
  2570                              <1> ;	; DL=2
  2571                              <1> ;iopen_0:
  2572                              <1> ;       cmp	ax, 40
  2573                              <1> ;		; cmp r1,$40. / is it a special file
  2574                              <1> ;       ja	short iopen_retn
  2575                              <1> ;		; bgt 3f / no. 3f
  2576                              <1> 
  2577                              <1> 	; 05/12/2021
  2578                              <1> 	; DL = 0 -> open for read
  2579                              <1> 	; DL = 1 -> open for write
  2580                              <1> 	; 11/02/2022
  2581                              <1> 	; DL = 2 -> create (open for write)
  2582                              <1> 		    ; (caller: syscreat)
  2583                              <1> 
  2584 000056EC 52                  <1> 	push	edx ; *
  2585                              <1> 
  2586                              <1> 	; set permission/mode flag for 'access' 
  2587                              <1> 	;	(DX = 100h -> IREAD, DX = 80h -> IWRITE)
  2588                              <1> 
  2589 000056ED B601                <1> 	mov	dh, 1
  2590 000056EF 08D2                <1> 	or	dl, dl ; dl = 0, open for read	
  2591 000056F1 7404                <1> 	jz	short iopen_0 ; DX = IREAD (100h)
  2592                              <1> 	; dl = 1, open for write 
  2593                              <1> 	; or
  2594                              <1> 	; dl = 2, create (regular) file	; 11/02/2022
  2595 000056F3 FECE                <1> 	dec	dh
  2596 000056F5 B280                <1> 	mov	dl, 80h
  2597                              <1> 	; DX = IWRITE (80h)
  2598                              <1> iopen_0:
  2599                              <1> 	; 27/03/2021
  2600                              <1> 	;   EAX = inode number (in AX)
  2601                              <1> 	;    DX = access mode, 100h = read, 80h = write
  2602                              <1> 
  2603                              <1> 	; 24/06/2020 - Retro UNIX 386 v2	
  2604 000056F7 E873F6FFFF          <1> 	call	access
  2605                              <1> 		; jsr r0,access; 1 / get inode in core
  2606                              <1> 	
  2607                              <1> 	; 27/03/2021
  2608                              <1> 	; DX return value from 'access' subroutine
  2609                              <1> 	;    may be 100h, 20h, 04h for DX = 100h (IREAD) input
  2610                              <1> 	;	     80h, 10h, 02h for DX = 80h (IWRITE) input
  2611                              <1> 
  2612                              <1> 	; 05/12/2021
  2613 000056FC 5A                  <1> 	pop	edx ; * ; dl = 0 -> open for read
  2614                              <1> 			; dl = 1 -> open for write
  2615                              <1> 			; 11/02/2022
  2616                              <1> 			; dl = 2 -> create (regular) file
  2617                              <1> 			;	   (open for writing)
  2618                              <1> 	; 24/06/2020
  2619 000056FD 8A0D[E5680000]      <1> 	mov	cl, [i.flgs+1]
  2620                              <1> 
  2621 00005703 F6C180              <1> 	test	cl, 80h		; regular file ?
  2622 00005706 7525                <1> 	jnz	short iopen_1	; yes ; 05/12/2021
  2623 00005708 F6C120              <1> 	test	cl, 20h 	; device file ?
  2624                              <1> 	;jnz	short iopen_2	; yes
  2625                              <1> 	; 11/02/2022
  2626 0000570B 7414                <1> 	jz	short iopen_invf ; no, invalid file/inode !
  2627                              <1> 	; device file/inode
  2628 0000570D F6C202              <1> 	test	dl, 2 ; create file ?
  2629 00005710 7425                <1> 	jz	short iopen_2	; device file r/w (dl=0 or dl=1)
  2630                              <1> 	; an attempt to create a file 
  2631                              <1> 	; whith name of existing device file in same directory!
  2632                              <1> iopen_pdnd:
  2633 00005712 C705[D86D0000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; 11
  2633 0000571A 0000                <1>
  2634                              <1> 				; 'permission denied !' error
  2635                              <1> iopen_err:
  2636 0000571C E94CDBFFFF          <1> 	jmp	error
  2637                              <1> iopen_invf:
  2638                              <1> 	; invalid inode (flags)
  2639 00005721 C705[D86D0000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  2639 00005729 0000                <1>
  2640 0000572B EBEF                <1> 	jmp	short iopen_err
  2641                              <1> 
  2642                              <1> iopen_1:
  2643                              <1> 	; 05/12/2021
  2644                              <1> 	; (If open mode is 'write' and the file/inode is a directory,
  2645                              <1> 	;  open request will/must be rejected.)
  2646                              <1> 	;
  2647                              <1> 	; (If inode is a regular file and it is not a directory,
  2648                              <1> 	; there is nothing to do here, we need to return to 'sysopen'
  2649                              <1> 	; for completing the rest of file opening procedure.) 
  2650                              <1> 	
  2651 0000572D F6C140              <1> 	test	cl, 40h	; directory ?
  2652 00005730 74B9                <1> 	jz	short iopen_retn ; no
  2653                              <1> 	
  2654 00005732 20D2                <1> 	and	dl, dl ; open mode is 1 (write) 
  2655                              <1> 	;jz	short iopen_retn ; no
  2656                              <1> 	; 11/02/2022
  2657                              <1> 	; open mode 1 (write) or 2 (create)
  2658 00005734 75DC                <1> 	jnz	short iopen_pdnd ; 'permission denied !' error
  2659                              <1> ;iopen_retn:
  2660 00005736 C3                  <1> 	retn
  2661                              <1> 
  2662                              <1> 	; !!!	
  2663                              <1> 	; 'sysopen' for writing
  2664                              <1> 	;	 is not applicable for directories
  2665                              <1> 	; (Directory entries must be created or deleted by
  2666                              <1> 	; relevant system calls.)
  2667                              <1> 
  2668                              <1> 	;;mov	dword [u.error], ERR_DIR_ACCESS ; 11
  2669                              <1> 	;mov	dword [u.error], ERR_PERM_DENIED ; 11
  2670                              <1> 	;			; 'permission denied !' error
  2671                              <1> 	;;jmp	error
  2672                              <1> 	;jmp	short iopen_err
  2673                              <1> 
  2674                              <1> ;iopen_retn:
  2675                              <1> ;	retn
  2676                              <1> 
  2677                              <1> iopen_2:
  2678                              <1> 	;push	ax
  2679                              <1> 	;	; mov r1,-(sp) / yes, figure out
  2680                              <1> 	;movzx	ebx, al
  2681                              <1> 	;shl	bx, 2
  2682                              <1> 	;	; asl r1
  2683                              <1>         ;add	ebx, iopen_1 - 4
  2684                              <1> 	;jmp	dword [ebx]
  2685                              <1>         ;	; jmp *1f-2(r1) / which one and transfer to it
  2686                              <1> 	
  2687                              <1> 	; 05/12/2021
  2688 00005737 50                  <1> 	push	eax ; save inode number
  2689                              <1> 	; device file
  2690 00005738 BB[54570000]        <1> 	mov	ebx, iopen_4
  2691 0000573D 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2692 00005740 720E                <1> 	jb	short iopen_3 ; null
  2693 00005742 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2694 00005745 7709                <1> 	ja	short iopen_3 ; null	
  2695                              <1> 	; convert v2 inode number to v1 device inode number
  2696 00005747 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2697 00005749 89C1                <1> 	mov	ecx, eax
  2698 0000574B C0E102              <1> 	shl	cl, 2 ; * 4
  2699 0000574E 01CB                <1> 	add	ebx, ecx
  2700                              <1> iopen_3:
  2701 00005750 FEC2                <1> 	inc	dl ; 1 = read, 2 = write
  2702 00005752 FF23                <1> 	jmp	dword [ebx]	
  2703                              <1> 		; jmp *1f-2(r1)
  2704                              <1> ;iopen_1: ; 1:
  2705                              <1> iopen_4:
  2706 00005754 [8E500000]          <1> 	dd	null ; 05/12/2021
  2707 00005758 [A4570000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2708                              <1>  		 ;otty / tty ; r1=2
  2709                              <1>         	 ;oppt / ppt ; r1=4
  2710 0000575C [5C580000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2711                              <1> 		 ;sret / mem ; r1=6
  2712                              <1> 		 ;sret / rf0
  2713                              <1>         	 ;sret / rk0
  2714                              <1>         	 ;sret / tap0
  2715                              <1>         	 ;sret / tap1
  2716                              <1>         	 ;sret / tap2
  2717                              <1>         	 ;sret / tap3
  2718                              <1>         	 ;sret / tap4
  2719                              <1>         	 ;sret / tap5
  2720                              <1>         	 ;sret / tap6
  2721                              <1>         	 ;sret / tap7
  2722 00005760 [5C580000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2723 00005764 [5C580000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2724 00005768 [5C580000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2725 0000576C [5C580000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2726 00005770 [5C580000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2727 00005774 [5C580000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2728                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2729                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2730                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2 (lpt_init)
  2731 00005778 [38590000]          <1>         dd	ejec ; lpr, AX = 9 (runix)	
  2732 0000577C [B5570000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2733                              <1> 		 ;ocvt / tty0
  2734 00005780 [B5570000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2735                              <1> 		 ;ocvt / tty1
  2736 00005784 [B5570000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2737                              <1> 		 ;ocvt / tty2
  2738 00005788 [B5570000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2739                              <1> 		 ;ocvt / tty3
  2740 0000578C [B5570000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2741                              <1> 		 ;ocvt / tty4
  2742 00005790 [B5570000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2743                              <1> 		 ;ocvt / tty5
  2744 00005794 [B5570000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2745                              <1> 		 ;ocvt / tty6
  2746 00005798 [B5570000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2747                              <1> 		 ;ocvt / tty7
  2748 0000579C [B5570000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2749                              <1> 		 ;error / crd
  2750 000057A0 [B5570000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2751                              <1> 
  2752                              <1> ;iopen_2: ; 2: / check open write access
  2753                              <1> ;	neg	ax
  2754                              <1> ;		; neg r1 / make inode number positive
  2755                              <1> ;	mov	dl, 1 ; write access
  2756                              <1> ;	call	access
  2757                              <1> ;		; jsr r0,access; 1 / get inode in core
  2758                              <1> ;	; DL=1
  2759                              <1> ;	test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2760                              <1> ;		;bit $40000,i.flgs / is it a directory?
  2761                              <1> ;	jz	short iopen_0
  2762                              <1> ;	;mov	[u.error], ERR_DIR_ACCESS
  2763                              <1> ;	;jmp	error ; permission denied !
  2764                              <1> ;	jmp	sysmnt_err0
  2765                              <1> ;	;;jnz	error		
  2766                              <1> ;      		; bne 2f / yes, transfer (error)
  2767                              <1> ;       ;;jmp     short iopen_0
  2768                              <1> ;	;cmp	ax, 40
  2769                              <1> ;		; cmp r1,$40. / no, is it a special file?
  2770                              <1> ;        ;ja	short iopen_2
  2771                              <1> ;		; bgt 3f / no, return
  2772                              <1> ;	;push	ax
  2773                              <1> ;		; mov r1,-(sp) / yes
  2774                              <1> ;	;movzx	ebx, al
  2775                              <1> ;	;shl	bx, 1
  2776                              <1> ;		; asl r1
  2777                              <1> ;	;add	ebx, ipen_3 - 2
  2778                              <1> ;	;jmp	dword [ebx]
  2779                              <1> ;		; jmp *1f-2(r1) / figure out 
  2780                              <1> ;			; / which special file it is and transfer
  2781                              <1> ;iopen_3: ; 1:
  2782                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2783                              <1> ; 		 ;otty / tty ; r1=2
  2784                              <1> ;        	 ;leadr / ppt ; r1=4
  2785                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2786                              <1> ;		 ;sret / mem ; r1=6
  2787                              <1> ;		 ;sret / rf0
  2788                              <1> ;        	 ;sret / rk0
  2789                              <1> ;        	 ;sret / tap0
  2790                              <1> ;        	 ;sret / tap1
  2791                              <1> ;        	 ;sret / tap2
  2792                              <1> ;        	 ;sret / tap3
  2793                              <1> ;        	 ;sret / tap4
  2794                              <1> ;        	 ;sret / tap5
  2795                              <1> ;        	 ;sret / tap6
  2796                              <1> ;        	 ;sret / tap7
  2797                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2798                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2799                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2800                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2801                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2802                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2803                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2804                              <1> ;	;dd	ejec ; lpr, AX = 9  (runix)
  2805                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2806                              <1> ;		 ;ocvt / tty0
  2807                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2808                              <1> ;		 ;ocvt / tty1
  2809                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2810                              <1> ;		 ;ocvt / tty2
  2811                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2812                              <1> ;		 ;ocvt / tty3
  2813                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2814                              <1> ;		 ;ocvt / tty4
  2815                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2816                              <1> ;		 ;ocvt / tty5
  2817                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2818                              <1> ;		 ;ocvt / tty6
  2819                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2820                              <1> ;		 ;ocvt / tty7
  2821                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2822                              <1> ;		 ;/ ejec / lpr
  2823                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2824                              <1> 
  2825                              <1> otty: ;/ open console tty for reading or writing
  2826                              <1> 	; 03/03/2022
  2827                              <1> 	; 23/02/2022
  2828                              <1> 	; 22/02/2022
  2829                              <1> 	; 09/02/2022
  2830                              <1> 	; 06/02/2022
  2831                              <1> 	; 08/01/2022
  2832                              <1> 	; 01/01/2022
  2833                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2834                              <1> 	; 16/11/2015
  2835                              <1> 	; 12/11/2015
  2836                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2837                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2838                              <1> 	; 16/07/2013
  2839                              <1> 	; Retro UNIX 8086 v1 modification:
  2840                              <1> 	;  If a tty is open for read or write by
  2841                              <1> 	;     a process (u.uno), only same process can open
  2842                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2843                              <1> 	;
  2844                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2845                              <1> 	;
  2846                              <1> 
  2847 000057A4 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2848 000057AB 8A83[63690000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2849                              <1> 	; 13/01/2014
  2850                              <1> 	;jmp	short ottyp
  2851                              <1> 	; 23/02/2022
  2852 000057B1 88C4                <1> 	mov	ah, al
  2853                              <1> 	; 06/02/2022
  2854 000057B3 EB06                <1> 	jmp	short otty_0
  2855                              <1> ocvt:
  2856 000057B5 2C0A                <1> 	sub	al, 10
  2857                              <1> ;ottyp:	; (call from sysstty)
  2858                              <1> 	; 08/01/2022
  2859 000057B7 31DB                <1> 	xor	ebx, ebx
  2860                              <1> ottyp:	; 03/03/2022
  2861                              <1> 	; (ebx < 256) ; 06/02/2022
  2862                              <1> 	; 23/02/2022
  2863 000057B9 B4FF                <1> 	mov	ah, 0FFh
  2864                              <1> 	; 22/02/2022
  2865                              <1> otty_0:
  2866                              <1> 	; 09/02/2022
  2867                              <1> 	; INPUT:
  2868                              <1> 	;	DL=1 for read, DL=2 for write, DL=0 for sysstty
  2869                              <1> 	;
  2870                              <1> 	; 08/01/2022
  2871                              <1> 	; 01/01/2022
  2872                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2873                              <1> 	; 16/11/2015
  2874                              <1> 	; 12/11/2015
  2875                              <1> 	; 18/05/2015 (32 bit modifications)
  2876                              <1> 	; 06/12/2013 - 13/07/2014
  2877 000057BB 88C6                <1> 	mov	dh, al ; tty number
  2878                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2879                              <1> 	; 08/01/2022
  2880 000057BD 88C3                <1> 	mov	bl, al
  2881 000057BF D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2882                              <1> 	; 26/01/2014	
  2883 000057C1 81C3[74680000]      <1> 	add 	ebx, ttyl
  2884 000057C7 668B0B              <1> 	mov 	cx, [ebx]
  2885                              <1> 		   ; CL = lock value (0 or process number)
  2886                              <1> 		   ; CH = open count 
  2887 000057CA 20C9                <1> 	and 	cl, cl
  2888                              <1> 	; 13/01/2014
  2889                              <1> 	;jz 	short otty_ret
  2890                              <1> 	; 05/12/2021
  2891 000057CC 7447                <1> 	jz 	short ottys_0
  2892                              <1> 	;
  2893                              <1> 	; 16/11/2015
  2894 000057CE 3A0D[B56D0000]      <1> 	cmp 	cl, [u.uno]
  2895 000057D4 746E                <1> 	je	short ottys_3
  2896                              <1> 	;
  2897                              <1> 	; 23/02/2022
  2898                              <1> 	; (is it the console tty of the current process?)
  2899                              <1> 	; ((fast check/permit for console tty open function))
  2900 000057D6 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2901 000057D8 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2902                              <1> 	;
  2903                              <1> 	;
  2904                              <1> 	; 22/02/2022
  2905                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2906                              <1> 	;shl 	bl, 1
  2907                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2908                              <1> 	;;movzx ebx, byte [u.uno]
  2909                              <1> 	;mov	bl, [u.uno]
  2910                              <1> 	;shl 	bl, 1
  2911                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2912                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2913                              <1> 	; 22/02/2022 (BugFix) ; *
  2914 000057DA 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2915 000057DD D1E6                <1> 	shl 	esi, 1
  2916 000057DF 668B86[22690000]    <1> 	mov 	ax, [esi+p.pid-2]
  2917 000057E6 96                  <1> 	xchg	esi, eax
  2918 000057E7 A0[B56D0000]        <1> 	mov	al, [u.uno]
  2919 000057EC D0E0                <1> 	shl 	al, 1
  2920 000057EE 663BB0[42690000]    <1> 	cmp 	si, [eax+p.ppid-2]	
  2921 000057F5 744D                <1> 	je 	short ottys_3 ; *
  2922                              <1> 	; 23/02/2022
  2923                              <1> 	; check console tty of the process
  2924                              <1> 	; (open permission must be given if the -requested- tty is
  2925                              <1> 	;  console tty of current process)
  2926 000057F7 D0E8                <1> 	shr	al, 1
  2927 000057F9 38B0[63690000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2928 000057FF 7443                <1> 	je 	short ottys_3
  2929                              <1> 	;
  2930                              <1> 	; the tty is locked by another process
  2931                              <1> 	; except the parent process (p.ppid)
  2932                              <1>         ; 09/02/2022
  2933                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2934                              <1> 	;		; permission denied ! error
  2935                              <1> otty_err: ; 13/01/2014
  2936                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2937                              <1> 	;;jnz	error
  2938                              <1> 	; 05/12/2021
  2939                              <1> 	;jz	short otty_stc_retn
  2940                              <1> 	;jmp	error
  2941                              <1> 	; 09/02/2022
  2942 00005801 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2943 00005804 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2944                              <1> 	; iopen (dl=1 or dl=2)
  2945 00005806 C705[D86D0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2945 0000580E 0000                <1>
  2946                              <1> 			; permission denied ! error
  2947 00005810 E958DAFFFF          <1> 	jmp	error
  2948                              <1> ;otty_stc_retn:
  2949                              <1> 	;stc
  2950                              <1> 	;retn
  2951                              <1> ottys_0:
  2952                              <1> 	; 05/12/2021
  2953                              <1> otty_ret:
  2954                              <1> 	; 13/01/2014
  2955 00005815 80FE07              <1> 	cmp 	dh, 7
  2956 00005818 7624                <1> 	jna	short ottys_2
  2957                              <1> 	; 16/11/2015
  2958                              <1> com_port_check:
  2959 0000581A BE[92680000]        <1> 	mov	esi, com1p
  2960 0000581F 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2961 00005822 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2962 00005824 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2963                              <1> ottys_1:
  2964                              <1> 	; 12/11/2015
  2965 00005825 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2966 00005828 7714                <1> 	ja	short com_port_ready
  2967                              <1> 	;
  2968                              <1> 	; 09/02/2022
  2969 0000582A 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2970 0000582D 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2971 0000582F C705[D86D0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2971 00005837 0000                <1>
  2972                              <1> 			   ; device not ready ! error
  2973                              <1> 	;jmp	short otty_err
  2974 00005839 E92FDAFFFF          <1> 	jmp	error	 
  2975                              <1> com_port_ready:
  2976                              <1> ottys_2:
  2977                              <1> 	; 03/03/2022
  2978                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2979                              <1> 	;jnz	short ottys_3
  2980 0000583E 8A0D[B56D0000]      <1> 	mov	cl, [u.uno]
  2981                              <1> ottys_3:
  2982 00005844 FEC5                <1> 	inc 	ch
  2983 00005846 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2984                              <1> 	; 06/12/2013
  2985 00005849 FEC6                <1> 	inc	dh ; tty number + 1
  2986 0000584B BB[9A6D0000]        <1> 	mov	ebx, u.ttyp
  2987                              <1> 	; 13/01/2014
  2988                              <1> 	;test	dl, 2 ; open for read sign
  2989                              <1> 	;jnz	short ottys_4
  2990                              <1> 	; 05/12/2021
  2991                              <1> 	;test	dl, 2
  2992                              <1> 	;jz	short ottys_4 ; open for read
  2993                              <1> 	; 01/01/2022
  2994 00005850 F6C201              <1> 	test	dl, 1
  2995 00005853 7501                <1> 	jnz	short ottys_4 ; open for read (dl=1)
  2996                              <1> 	; dl=2 (open for write) or dl=0 (sysstty)
  2997 00005855 43                  <1> 	inc	ebx
  2998                              <1> ottys_4:
  2999                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  3000 00005856 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  3001                              <1> 	; 09/02/2022
  3002 00005858 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3003 0000585A 7401                <1> 	jz	short otty_retn ; 03/03/2022
  3004                              <1> sret:
  3005                              <1> 	;pop 	ax
  3006                              <1> 	; 05/12/2021
  3007 0000585C 58                  <1> 	pop	eax
  3008                              <1> otty_retn:	; 09/02/2022
  3009                              <1> iclose_retn:	
  3010 0000585D C3                  <1> 	retn
  3011                              <1> 
  3012                              <1> 	;
  3013                              <1> 	; Original UNIX v1 'otty' routine:
  3014                              <1> 	;	
  3015                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  3016                              <1>         ;                 / reader status reg
  3017                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  3018                              <1>         ;                 / punch status reg
  3019                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  3020                              <1>         ;                          / console tty buffer
  3021                              <1>         ;incb   (r5) / increment the count of processes that opened the
  3022                              <1>         ;            / console tty
  3023                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  3024                              <1>         ;             / buffer header
  3025                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  3026                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  3027                              <1>         ;                 / tty
  3028                              <1>         ;br     sret / ?
  3029                              <1> ;sret:
  3030                              <1> 		;clr *$ps / set processor priority to zero
  3031                              <1> ;	pop	ax
  3032                              <1>         	;mov (sp)+,r1 / pop stack to r1
  3033                              <1> ;3:
  3034                              <1> ;	retn
  3035                              <1>         	;rts r0
  3036                              <1> 	
  3037                              <1> ;ocvt:	; < open tty >
  3038                              <1> 	; 13/01/2014
  3039                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  3040                              <1> 	; 24/09/2013 consistency check -> ok
  3041                              <1> 	; 16/09/2013
  3042                              <1> 	; 03/09/2013
  3043                              <1> 	; 27/08/2013
  3044                              <1> 	; 16/08/2013
  3045                              <1> 	; 16/07/2013
  3046                              <1> 	; 27/05/2013
  3047                              <1> 	; 21/05/2013
  3048                              <1> 	;
  3049                              <1> 	; Retro UNIX 8086 v1 modification !
  3050                              <1> 	; 
  3051                              <1> 	; In original UNIX v1, 'ocvt' routine 
  3052                              <1> 	;		(exactly different than this one)
  3053                              <1> 	;	was in 'u9.s' file.
  3054                              <1> 	;
  3055                              <1> 	; 16/07/2013
  3056                              <1> 	; Retro UNIX 8086 v1 modification:
  3057                              <1> 	;  If a tty is open for read or write by
  3058                              <1> 	;     a process (u.uno), only same process can open
  3059                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  3060                              <1> 	;
  3061                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  3062                              <1> 
  3063                              <1> 	; 16/09/2013
  3064                              <1> 	; sub 	al, 10
  3065                              <1> 	
  3066                              <1> 	; 06/12/2013
  3067                              <1> 	;cmp	al, 7
  3068                              <1>         ;jna	short ottyp
  3069                              <1> 	; 13/01/2014
  3070                              <1> 	;jmp	short ottyp
  3071                              <1> 
  3072                              <1> ;oppt: / open paper tape for reading or writing
  3073                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  3074                              <1> ;        tstb   pptiflg / is file already open
  3075                              <1> ;        bne    2f / yes, branch
  3076                              <1> ;1:
  3077                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  3078                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  3079                              <1> ;               br .+4 / for paper tape input and place in free list
  3080                              <1> ;        br     1b
  3081                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  3082                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  3083                              <1> ;        br     sret
  3084                              <1> ;2:
  3085                              <1> ;        jmp    error / file already open
  3086                              <1> 
  3087                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  3088                              <1> iclose:
  3089                              <1> 	; 09/02/2022
  3090                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  3091                              <1> 	; 10/04/2021
  3092                              <1> 	; 08/04/2021
  3093                              <1> 	; 04/04/2021 - Retro UNIX 386 v2
  3094                              <1> 	; 19/05/2015
  3095                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3096                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3097                              <1> 	;
  3098                              <1> 	; close file whose i-number is in r1
  3099                              <1> 	; 
  3100                              <1> 	; INPUTS ->
  3101                              <1> 	;    r1 - inode number
  3102                              <1> 	; OUTPUTS ->
  3103                              <1> 	;    file's inode in core	
  3104                              <1> 	;    r1 - inode number (positive)
  3105                              <1> 	;
  3106                              <1> 	; ((AX = R1))
  3107                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  3108                              <1> 	;        
  3109                              <1> ;;/ close file whose i-number is in r1
  3110                              <1> ;	mov	dl, 2 ; 12/01/2014
  3111                              <1> ;	test	ah, 80h ; Bit 15 of AX
  3112                              <1> ;		;tst r1 / test i-number
  3113                              <1> ;	;jnz	short iclose_2
  3114                              <1> ;		;blt 2f / if neg., branch
  3115                              <1> ;	jz	short iclose_0 ; 30/07/2013
  3116                              <1> ;	; 16/07/2013 
  3117                              <1> ;	neg	ax ; make it positive
  3118                              <1> ;	; 12/01/2014
  3119                              <1> ;	dec	dl ; dl = 1 (open for write)
  3120                              <1> ;iclose_0:
  3121                              <1> ;	cmp	ax, 40
  3122                              <1> ;		;cmp r1,$40. / is it a special file
  3123                              <1> ;       ja	short iclose_retn  ; 13/01/2014
  3124                              <1> ;		;bgt 3b / no, return
  3125                              <1> ;	; 12/01/2014
  3126                              <1> ;	; DL=2 -> special file was opened for reading
  3127                              <1> ;	; DL=1 -> special file was opened for writing
  3128                              <1> 
  3129                              <1> 	; 04/04/2021
  3130                              <1> 	; INPUT:
  3131                              <1> 	;	(e)ax = inode number
  3132                              <1> 	;	   dl = open mode
  3133                              <1> 	;		0 = control mode
  3134                              <1> 	;		1 = read
  3135                              <1> 	;		2 = write
  3136                              <1> 	; OUTPUT:
  3137                              <1> 	;	none
  3138                              <1> 	;	(if cf=1 -> eax = error code)
  3139                              <1> 	;	(if cf=0 -> ax = inode number)
  3140                              <1> 
  3141                              <1> 	; 10/04/2021
  3142                              <1>         ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 
  3143                              <1> 
  3144                              <1> 	; 05/12/2021
  3145                              <1> 	; 08/04/2021
  3146                              <1> 
  3147 0000585E 52                  <1> 	push	edx
  3148 0000585F E821F4FFFF          <1> 	call	iget
  3149 00005864 5A                  <1> 	pop	edx 
  3150                              <1> 
  3151 00005865 8A0D[E5680000]      <1> 	mov	cl, [i.flgs+1]
  3152                              <1> 
  3153                              <1> 	; if i.flgs bit 15 is 1, it is regular file 
  3154                              <1> 	;test	byte [i.flgs+1], 80h ; is it a special file?
  3155 0000586B F6C180              <1> 	test	cl, 80h ; is it a special file?
  3156 0000586E 75ED                <1> 	jnz	short iclose_retn ; no
  3157                              <1> 
  3158                              <1> 	;; inode flags - bit 13 must be 1 
  3159                              <1> 	;test	cl, 20h ; is it a valid device inode
  3160                              <1> 	;jz	short iclose_retn ; no ; 19/01/2022
  3161                              <1> 	
  3162                              <1> 	;push	ax
  3163                              <1> 	;	;mov r1,-(sp) / yes, save r1 on stack
  3164                              <1> 	;movzx	ebx, al
  3165                              <1> 	;shl	bx, 2
  3166                              <1> 	;	; asl r1
  3167                              <1> 	;add	ebx, iclose_1 - 4
  3168                              <1> 	;jmp	dword [ebx]
  3169                              <1> 	;	; jmp *1f-2(r1) / compute jump address and transfer
  3170                              <1> 
  3171                              <1> 	; 05/12/2021
  3172 00005870 50                  <1> 	push	eax ; save inode number
  3173                              <1> 	; device file
  3174 00005871 BB[8B580000]        <1> 	mov	ebx, iclose_1
  3175 00005876 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  3176 00005879 720E                <1> 	jb	short iclose_0
  3177 0000587B 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  3178 0000587E 7709                <1> 	ja	short iclose_0
  3179                              <1> 	; convert v2 inode number to v1 device inode number
  3180 00005880 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  3181 00005882 89C1                <1> 	mov	ecx, eax
  3182 00005884 C0E102              <1> 	shl	cl, 2 ; * 4
  3183 00005887 01CB                <1> 	add	ebx, ecx
  3184                              <1> iclose_0:
  3185 00005889 FF23                <1> 	jmp	dword [ebx]	
  3186                              <1> 		; jmp *1f-2(r1)
  3187                              <1> iclose_1: ; 1:
  3188 0000588B [8E500000]          <1> 	dd	null ; 05/12/2021
  3189 0000588F [DB580000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  3190 00005893 [36590000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  3191 00005897 [36590000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  3192 0000589B [36590000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  3193 0000589F [36590000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  3194 000058A3 [36590000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  3195 000058A7 [36590000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  3196 000058AB [36590000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  3197 000058AF [36590000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  3198                              <1> 	;dd	error; lpr, AX = 9 (error!)
  3199                              <1> 	;;dd	ejec ;;lpr, AX = 9  
  3200 000058B3 [EA580000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  3201 000058B7 [EA580000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  3202 000058BB [EA580000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  3203 000058BF [EA580000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  3204 000058C3 [EA580000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  3205 000058C7 [EA580000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  3206 000058CB [EA580000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  3207 000058CF [EA580000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  3208 000058D3 [EA580000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  3209 000058D7 [EA580000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  3210                              <1> 
  3211                              <1> 	; 1:
  3212                              <1> 	;        ctty   / tty
  3213                              <1> 	;        cppt   / ppt
  3214                              <1> 	;        sret   / mem
  3215                              <1> 	;        sret   / rf0
  3216                              <1> 	;        sret   / rk0
  3217                              <1> 	;        sret   / tap0
  3218                              <1> 	;        sret   / tap1
  3219                              <1> 	;        sret   / tap2
  3220                              <1> 	;        sret   / tap3
  3221                              <1> 	;        sret   / tap4
  3222                              <1> 	;        sret   / tap5
  3223                              <1> 	;        sret   / tap6
  3224                              <1> 	;        sret   / tap7
  3225                              <1> 	;        ccvt   / tty0
  3226                              <1> 	;        ccvt   / tty1
  3227                              <1> 	;        ccvt   / tty2
  3228                              <1> 	;        ccvt   / tty3
  3229                              <1> 	;        ccvt   / tty4
  3230                              <1> 	;        ccvt   / tty5
  3231                              <1> 	;        ccvt   / tty6
  3232                              <1> 	;        ccvt   / tty7
  3233                              <1> 	;        error / crd
  3234                              <1> 
  3235                              <1> ;iclose_2: ; 2: / negative i-number
  3236                              <1> 	;neg	ax
  3237                              <1> 		;neg r1 / make it positive
  3238                              <1> 	;cmp	ax, 40
  3239                              <1> 		;cmp r1,$40. / is it a special file?
  3240                              <1>         ;ja	short @b
  3241                              <1> 		;bgt 3b / no. return
  3242                              <1> 	;push	ax
  3243                              <1> 		;mov r1,-(sp)
  3244                              <1> 	;movzx	ebx, al
  3245                              <1> 	;shl	bx, 1
  3246                              <1> 		;asl r1 / yes. compute jump address and transfer
  3247                              <1> 	;add	ebx, iclose_3 - 2
  3248                              <1> 	;jmp	dword [ebx]
  3249                              <1> 		;jmp *1f-2(r1) / figure out 
  3250                              <1> ;iclose_3:
  3251                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  3252                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  3253                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  3254                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  3255                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  3256                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  3257                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3258                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3259                              <1> 	;;dd	sret ; lpr, AX = 9	
  3260                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3261                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3262                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3263                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3264                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3265                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3266                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3267                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3268                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3269                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3270                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3271                              <1> 	
  3272                              <1> 	;1:
  3273                              <1> 	;      	ctty   / tty
  3274                              <1> 	;       leadr  / ppt
  3275                              <1> 	;       sret   / mem
  3276                              <1> 	;       sret   / rf0
  3277                              <1> 	;       sret   / rk0
  3278                              <1> 	;       sret   / tap0
  3279                              <1> 	;       sret   / tap1
  3280                              <1> 	;       sret   / tap2
  3281                              <1> 	;       sret   / tap3
  3282                              <1> 	;       sret   / tap4
  3283                              <1> 	;       sret   / tap5
  3284                              <1> 	;       sret   / tap6
  3285                              <1> 	;       sret   / tap7
  3286                              <1> 	;       ccvt   / tty0
  3287                              <1> 	;       ccvt   / tty1
  3288                              <1> 	;       ccvt   / tty2
  3289                              <1> 	;       ccvt   / tty3
  3290                              <1> 	;       ccvt   / tty4
  3291                              <1> 	;       ccvt   / tty5
  3292                              <1> 	;       ccvt   / tty6
  3293                              <1> 	;       ccvt   / tty7
  3294                              <1> 	;/      ejec   / lpr
  3295                              <1> 
  3296                              <1> ctty: ; / close console tty
  3297                              <1> 	; 09/02/2022
  3298                              <1> 	; 06/02/2022
  3299                              <1> 	; 08/01/2022
  3300                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3301                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3302                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3303                              <1> 	;
  3304                              <1> 	; Retro UNIX 8086 v1 modification !
  3305                              <1> 	; (DL = 2 -> it is open for reading)
  3306                              <1> 	; (DL = 1 -> it is open for writing)
  3307                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3308                              <1> 	;
  3309                              <1> 	; 06/12/2013
  3310 000058DB 0FB61D[B56D0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3311 000058E2 8A83[63690000]      <1>         mov     al, [ebx+p.ttyc-1]
  3312                              <1> 	; 13/01/2014
  3313                              <1> 	;jmp	short cttyp
  3314                              <1> 	; 06/02/2022
  3315 000058E8 EB04                <1> 	jmp	short ctty_0
  3316                              <1> ccvt:
  3317 000058EA 2C0A                <1> 	sub 	al, 10
  3318                              <1> cttyp:
  3319                              <1> 	; 08/01/2022
  3320 000058EC 31DB                <1> 	xor	ebx, ebx
  3321                              <1> ctty_0:		; 06/02/2022
  3322                              <1> 	; 09/02/2022
  3323                              <1> 	;    DL=2 -> open for writing
  3324                              <1> 	;    DL=1 -> open for reading
  3325                              <1> 	;    DL=0 -> open for sysstty system call	
  3326                              <1> 	; 08/01/2022
  3327                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3328                              <1> 	; 18/05/2015 (32 bit modifications)
  3329                              <1> 	; 16/08/2013 - 26/01/2014
  3330                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3331                              <1> 	; 08/01/2022
  3332 000058EE 88C3                <1> 	mov	bl, al
  3333 000058F0 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3334                              <1> 	; 26/01/2014
  3335 000058F2 81C3[74680000]      <1> 	add 	ebx, ttyl
  3336 000058F8 88C6                <1> 	mov 	dh, al ; tty number
  3337 000058FA 668B03              <1> 	mov 	ax, [ebx]
  3338                              <1> 		   ; AL = lock value (0 or process number)
  3339                              <1> 		   ; AH = open count 
  3340 000058FD 20E4                <1> 	and 	ah, ah
  3341 000058FF 7514                <1> 	jnz	short ctty_ret
  3342                              <1> 	; 09/02/2022
  3343 00005901 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3344 00005904 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3345                              <1> 	; iclose (dl=1 or dl=2)
  3346 00005906 C705[D86D0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3346 0000590E 0000                <1>
  3347                              <1> 			; device not open ! error
  3348                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3349 00005910 E958D9FFFF          <1> 	jmp	error
  3350                              <1> 	; 26/01/2014
  3351                              <1> ctty_ret:
  3352 00005915 FECC                <1> 	dec 	ah ; decrease open count
  3353 00005917 7502                <1> 	jnz	short ctty_1
  3354 00005919 30C0                <1> 	xor	al, al ; unlock/free tty
  3355                              <1> ctty_1:
  3356 0000591B 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3357                              <1> 	;
  3358 0000591E BB[9A6D0000]        <1> 	mov	ebx, u.ttyp
  3359                              <1> 	;;test	dl, 1 ; open for write sign
  3360                              <1> 	;;jz	short ctty_2
  3361                              <1> 	; 05/12/2021
  3362                              <1> 	;test	dl, 2 ; open for write sign
  3363                              <1> 	;jz	short ctty_2	
  3364                              <1> 	; 09/02/2022
  3365 00005923 F6C201              <1> 	test	dl, 1 ; open for read sign
  3366 00005926 7501                <1> 	jnz	short ctty_2
  3367                              <1> 	; open for write (dl=0 or dl=2)
  3368 00005928 43                  <1> 	inc	ebx
  3369                              <1> ctty_2:
  3370 00005929 FEC6                <1> 	inc	dh ; tty number + 1
  3371 0000592B 3A33                <1> 	cmp	dh, [ebx]
  3372                              <1> 	;jne	short cret
  3373 0000592D 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3374                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3375 0000592F C60300              <1> 	mov	byte [ebx], 0
  3376                              <1> ctty_3:
  3377                              <1> 	; 09/02/2022
  3378 00005932 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3379 00005934 7401                <1> 	jz	short ctty_4
  3380                              <1> cret:
  3381                              <1> 	;pop	ax
  3382                              <1> 	; 05/12/2021
  3383 00005936 58                  <1> 	pop	eax
  3384                              <1> ctty_stc_retn:	; 09/02/2022
  3385                              <1> ctty_4:
  3386 00005937 C3                  <1> 	retn
  3387                              <1> 
  3388                              <1> ;ctty_err: ; 13/01/2014
  3389                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3390                              <1> ;	jnz	error
  3391                              <1> ;	stc
  3392                              <1> ;	retn
  3393                              <1> 
  3394                              <1> 	; Original UNIX v1 'ctty' routine:
  3395                              <1> 	;	
  3396                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3397                              <1> 	;		;/ point r5 to the console tty buffer
  3398                              <1>         ;decb   (r5) / dec number of processes using console tty
  3399                              <1>         ;br     sret / return via sret
  3400                              <1> 
  3401                              <1> ;ccvt:	; < close tty >
  3402                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3403                              <1> 	;
  3404                              <1> 	; Retro UNIX 8086 v1 modification !
  3405                              <1> 	; 
  3406                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3407                              <1> 	;		(exactly different than this one)
  3408                              <1> 	;	was in 'u9.s' file.
  3409                              <1> 	;
  3410                              <1> 	; DL = 2 -> it is open for reading
  3411                              <1> 	; DL = 1 -> it is open for writing
  3412                              <1> 	;
  3413                              <1> 	; 17/09/2013
  3414                              <1> 	;sub 	al, 10
  3415                              <1> 	;cmp	al, 7
  3416                              <1> 	;jna	short cttyp
  3417                              <1> 	; 13/01/2014
  3418                              <1> 	;jmp	short cttyp
  3419                              <1> 
  3420                              <1> ;cppt: / close paper tape
  3421                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3422                              <1> ;1:
  3423                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3424                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3425                              <1> ;                          / and assign to free list
  3426                              <1> ;               br sret
  3427                              <1> ;        br     1b
  3428                              <1> 
  3429                              <1> ;ejec:	
  3430                              <1> ;	jmp	error
  3431                              <1> ;/ejec:
  3432                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3433                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3434                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3435                              <1> ;/       br     sret / return to caller via 'sret'
  3436                              <1> 
  3437                              <1> ejec:
  3438                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2 - Printer Initialization
  3439                              <1> lpt_init:	
  3440                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3441                              <1> 	;
  3442                              <1> 	; Default printer port: 378h ; LPT1
  3443                              <1> 	
  3444 00005938 B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3445                              <1> 	;call	int17h
  3446 0000593A E84CFAFFFF          <1> 	call	PRNOP
  3447 0000593F 7414                <1> 	jz	short lpt_init_ok
  3448                              <1> 	
  3449                              <1> 	; replace error code with 'device not ready' error
  3450                              <1> 	; (this may be better for 'sysopen')
  3451 00005941 B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3452 00005946 A3[D86D0000]        <1> 	mov	[u.error], eax
  3453                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3454 0000594B A3[646D0000]        <1> 	mov	[u.r0], eax
  3455 00005950 E918D9FFFF          <1> 	jmp	error ; (better)	
  3456                              <1> 	
  3457                              <1> lpt_init_ok:
  3458                              <1> 	;jmp	short cret
  3459 00005955 58                  <1> 	pop	eax    ; inode number
  3460 00005956 C3                  <1> 	retn
  3461                              <1> 	
  2094                                  %include 'u8.s'      ; 11/06/2015
  2095                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2096                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2097                              <1> ; ****************************************************************************
  2098                              <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - SYS8.INC
  2099                              <1> ; Last Modification: 16/07/2022
  2100                              <1> ; ----------------------------------------------------------------------------
  2101                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2102                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2103                              <1> ;
  2104                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2105                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2106                              <1> ; <Bell Laboratories (17/3/1972)>
  2107                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2108                              <1> ;
  2109                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2110                              <1> ;
  2111                              <1> ; ****************************************************************************
  2112                              <1> 
  2113                              <1> ; 15/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2114                              <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2115                              <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2116                              <1> ;---------------------------------------------------------------------
  2117                              <1> ; Buffer Header: -8 bytes-
  2118                              <1> ; word 1 - byte 0 - device (disk index) number (0 to 5)
  2119                              <1> ;	   byte 1 - status bits
  2120                              <1> ;	 	bit 0 - valid buffer bit (1 = valid, 0 = invalid, new)
  2121                              <1> ;		bit 1 - write bit (also modified bit)
  2122                              <1> ;		bit 2 - read bit	
  2123                              <1> ;		bit 3 to bit 7 are not used
  2124                              <1> ; word 2 - byte & byte 3 not used
  2125                              <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7:
  2126                              <1> ;		physical block/sector address (32 bit LBA)
  2127                              <1> ;---------------------------------------------------------------------
  2128                              <1> 
  2129                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2130                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2131                              <1> ;; Word 1, byte 0 = device id
  2132                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2133                              <1> ;;          bit 9 = write bit
  2134                              <1> ;;	    bit 10 = read bit	  
  2135                              <1> ;;	    bit 12 = waiting to write bit	
  2136                              <1> ;;	    bit 13 = waiting to read bit
  2137                              <1> ;;	    bit 15 = inhibit bit
  2138                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2139                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2140                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2141                              <1> ;;
  2142                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2143                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2144                              <1> ;;
  2145                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2146                              <1> ;; Word 1, Byte 0 = device id
  2147                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2148                              <1> ;;          bit 9 = write bit
  2149                              <1> ;;	    bit 10 = read bit	  
  2150                              <1> ;;	    bit 12 = waiting to write bit	
  2151                              <1> ;;	    bit 13 = waiting to read bit
  2152                              <1> ;;	    bit 15 = inhibit bit
  2153                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2154                              <1> ;;
  2155                              <1> ;; Original UNIX v1 ->
  2156                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2157                              <1> ;; Original UNIX v1 -> 
  2158                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2159                              <1> ;;
  2160                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2161                              <1> ;;
  2162                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2163                              <1> ;;          0 = fd0
  2164                              <1> ;;	    1 = fd1
  2165                              <1> ;;	    2 = hd0
  2166                              <1> ;;	    3 = hd1
  2167                              <1> ;;	    4 = hd2
  2168                              <1> ;;	    5 = hd3
  2169                              <1> 
  2170                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2171                              <1> 
  2172                              <1> 	; 08/02/2022
  2173                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2174                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2175                              <1> 	; 26/04/2013
  2176                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2177                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2178                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2179                              <1> 
  2180                              <1> 	; 08/02/2022
  2181                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2182                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2183                              <1> 	; 26/04/2013
  2184                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2185                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2186                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2187                              <1> 
  2188                              <1> bread: 
  2189                              <1> 	; 15/07/2022
  2190                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2191                              <1> 	; 08/02/2022
  2192                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2193                              <1> 	; 14/07/2015
  2194                              <1> 	; 10/07/2015
  2195                              <1> 	; 09/06/2015
  2196                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2197                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2198                              <1> 	;	
  2199                              <1> 	; / read a block from a block structured device
  2200                              <1> 	;
  2201                              <1> 	; INPUTS ->
  2202                              <1> 	;    [u.fopf] points to the block number
  2203                              <1> 	;    ECX = maximum block number allowed on device
  2204                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2205                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2206                              <1> 	;    [u.count] number of bytes to read in
  2207                              <1> 	; OUTPUTS ->
  2208                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2209                              <1> 	;    [u.fopf] points to next consecutive block to be read
  2210                              <1> 	;
  2211                              <1> 	; ((Modified registers: eax, edx, ecx, ebx, esi, edi))
  2212                              <1> 	;
  2213                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2214                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2215                              <1> 	;	is increased by 1. For example: If user/program request 
  2216                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2217                              <1> 	;  	the next block number just as 512 byte reading is done.
  2218                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2219                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2220                              <1> 	;       enough to keep byte position/offset of the disk), this
  2221                              <1> 	;	defect will not be corrected, user/program must request
  2222                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2223                              <1> 	;       for achieving correct result. In future version(s), 
  2224                              <1> 	;	this defect will be corrected by using different 
  2225                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2226                              <1> 
  2227                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2228                              <1> 			       ; / (only works on tape)
  2229                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2230                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2231                              <1> ;1:
  2232                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2233                              <1> 			    ; / maximum block # allowed on device
  2234                              <1> 		; jnb short @f
  2235                              <1> 		; bhis	1f / yes, 1f (error)
  2236                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2237                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2238                              <1> 		; mov (sp)+,r1 / return block # to r1
  2239                              <1> 		; inc r1 / bump block # to next consecutive block
  2240                              <1> 		; dec (sp) / "2-1-cold" on stack
  2241                              <1> 		; bgt 1b / 2-1-cold = 0? No, go back and read in next block
  2242                              <1> ;1:
  2243                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2244                              <1> 	;push	ecx ; **
  2245                              <1> 	; 26/04/2013
  2246                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2247 00005957 2C03                <1> 	sub	al, 3
  2248                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2249 00005959 A2[D76D0000]        <1> 	mov	[u.brwdev], al
  2250                              <1> 	; 09/06/2015
  2251                              <1> 	;movzx	ebx, al
  2252                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2253                              <1> 	; 12/01/2022 (BugFix)
  2254 0000595E C0E002              <1> 	shl	al, 2 ; * 4
  2255 00005961 8B88[52630000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2256                              <1> bread_0:
  2257 00005967 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2258                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2259                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2260 00005968 8B1D[786D0000]      <1> 	mov	ebx, [u.fofp]
  2261 0000596E 8B03                <1> 	mov	eax, [ebx]
  2262 00005970 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2263                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2264                              <1> 			       ; / block #
  2265 00005973 39C8                <1> 	cmp	eax, ecx
  2266                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2267                              <1>        	                     ; / block number allowed
  2268                              <1> 	;jnb	error 	     ; 18/04/2013
  2269                              <1> 		; bhis error10 / yes, error
  2270                              <1> 	; 08/02/2022
  2271                              <1> 	;jb	short bread_1
  2272                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2273                              <1> 	;jmp	error
  2274 00005975 7342                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2275                              <1> bread_1:
  2276                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2277                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2278                              <1> 	; EAX = Block number (zero based)
  2279                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2280                              <1> preread: ;; call preread
  2281 00005977 BF[D76D0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2282 0000597C E8D9010000          <1> 	call	bufaloc_0 ; 26/04/2013
  2283                              <1> 	;; jc 	error
  2284                              <1> 	; EBX = Buffer (Header) Address -Physical-
  2285                              <1>         ; EAX = Block/Sector number (r1)
  2286                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2287                              <1> 	; 14/03/2013
  2288 00005981 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2289                              <1>        		; br 1f / branch if block already in a I/O buffer
  2290 00005983 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2291                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2292 00005988 E8A5010000          <1> 	call	poke
  2293                              <1>         	; jsr r0,poke / perform the read
  2294                              <1> 	;;jc	error ;2 0/07/2013
  2295                              <1> ; 1:
  2296                              <1>  		; clr *$ps / ps = 0
  2297                              <1>         	; rts r0
  2298                              <1> 	; 08/02/2022
  2299 0000598D 7305                <1> 	jnc	short bread_2
  2300 0000598F E911010000          <1> 	jmp	dskrd_err
  2301                              <1> 	;
  2302                              <1> ;; return from preread
  2303                              <1> bread_2:
  2304                              <1> 	; 15/07/2022
  2305                              <1> 	;or	word [ebx], 4000h 
  2306                              <1> 	;	; bis $40000,(r5) 
  2307                              <1> 	;		; / set bit 14 of the 1st word of the I/O buffer
  2308                              <1> bread_3: ; 1:
  2309                              <1> 	; 15/07/2022
  2310                              <1> 	;test	word [ebx], 2400h
  2311                              <1> 	;	; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2312                              <1> 	;jz	short bread_4
  2313                              <1> 	;	; beq 1f / no
  2314                              <1> 	;	; cmp cdev,$1 / disk or drum?
  2315                              <1> 	;	; ble 2f / yes
  2316                              <1> 	;	; tstb uquant / is the time quantum = 0?
  2317                              <1> 	;	; bne 2f / no, 2f
  2318                              <1> 	;	; mov r5,-(sp) / yes, save r5 (buffer address)
  2319                              <1> 	;	; jsr r0,sleep; 31. 
  2320                              <1> 	;		; / put process to sleep in channel 31 (tape)
  2321                              <1> 	;	; mov (sp)+,r5 / restore r5
  2322                              <1> 	;	; br 1b / go back
  2323                              <1> ; 2: / drum or disk
  2324                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2325                              <1> 	;call	idle
  2326                              <1> 	;	; jsr r0,idle; s.wait+2 / wait
  2327                              <1> 	;jmp	short bread_3
  2328                              <1>        	;	; br 1b
  2329                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2330                              <1> 	;and	word [ebx], 0BFFFh ; 1011111111111111b
  2331                              <1> 	;	; bic $40000,(r5) / clear bit 14
  2332                              <1>        	;	; jsr r0,tstdeve / test device for error (tape)
  2333                              <1> 	; 15/07/2022
  2334 00005994 83C308              <1> 	add	ebx, 8
  2335                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2336                              <1> 	; 09/06/2015
  2337 00005997 66833D[D06D0000]00  <1> 	cmp	word [u.pcount], 0
  2338 0000599F 7705                <1> 	ja	short bread_5
  2339 000059A1 E802F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2340                              <1> bread_5:
  2341                              <1> 	; EBX = system (I/O) buffer address
  2342 000059A6 E870000000          <1> 	call	dioreg
  2343                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2344                              <1> 	; esi = start address of the transfer (in the buffer)
  2345                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2346                              <1> 	; ecx = transfer count (in bytes)
  2347                              <1> 	;
  2348                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2349                              <1> ;   / of users data
  2350 000059AB F3A4                <1> 	rep	movsb
  2351                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2352                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2353                              <1>        		; bne 1b
  2354 000059AD 59                  <1> 	pop	ecx ; **
  2355 000059AE 833D[8C6D0000]00    <1> 	cmp	dword [u.count], 0
  2356                              <1> 		; tst u.count / done
  2357 000059B5 77B0                <1> 	ja	short bread_0 ; 09/06/2015
  2358                              <1>        		; beq 1f / yes, return
  2359                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2360                              <1>        		; br bread / read some more
  2361                              <1> ; 1:
  2362 000059B7 58                  <1> 	pop	eax ; ****
  2363                              <1>        		; mov (sp)+,r0
  2364 000059B8 C3                  <1>         retn		; 09/06/2015
  2365                              <1> 	;jmp	ret_ 
  2366                              <1> 		;jmp ret / jump to routine that called readi
  2367                              <1> 
  2368                              <1> 	; 08/02/2022
  2369                              <1> brw_oov_err:
  2370 000059B9 C705[D86D0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2370 000059C1 0000                <1>
  2371 000059C3 E9A5D8FFFF          <1> 	jmp	error
  2372                              <1> 
  2373                              <1> 	; 08/02/2022
  2374                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2375                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2376                              <1> 	; 26/04/2013
  2377                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2378                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2379                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2380                              <1> 
  2381                              <1> 	; 08/02/2022
  2382                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)				
  2383                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2384                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2385                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2386                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2387                              <1> 
  2388                              <1> bwrite:
  2389                              <1> 	; 15/07/2022
  2390                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3) 
  2391                              <1> 	; 08/02/2022
  2392                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2393                              <1> 	; 14/07/2015
  2394                              <1> 	; 10/07/2015
  2395                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2396                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2397                              <1> 	;	
  2398                              <1> 	;; / write on block structured device
  2399                              <1> 	;
  2400                              <1> 	; INPUTS ->
  2401                              <1> 	;    [u.fopf] points to the block number
  2402                              <1> 	;    ECX = maximum block number allowed on device
  2403                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2404                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2405                              <1> 	;    [u.count]	number of bytes to user desires to write
  2406                              <1> 	; OUTPUTS ->
  2407                              <1> 	;    [u.fopf] points to next consecutive block to be written into
  2408                              <1> 	;
  2409                              <1> 	; ((Modified registers: edx, ecx, ebx, esi, edi))
  2410                              <1> 	;
  2411                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2412                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2413                              <1> 	;	is increased by 1. For example: If user/program request 
  2414                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2415                              <1> 	;  	the next block number just as 512 byte writing is done.
  2416                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2417                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2418                              <1> 	;       enough to keep byte position/offset of the disk), this
  2419                              <1> 	;	defect will not be corrected, user/program must request
  2420                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2421                              <1> 	;       for achieving correct result. In future version(s), 
  2422                              <1> 	;	this defect will be corrected by using different 
  2423                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2424                              <1> 
  2425                              <1>        		; jsr r0,tstdeve / test the device for an error
  2426                              <1> 	;push	ecx ; **
  2427                              <1> 	;26/04/2013
  2428                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2429 000059C8 2C03                <1> 	sub	al, 3
  2430                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2431 000059CA A2[D76D0000]        <1> 	mov	[u.brwdev], al
  2432                              <1> 	; 09/06/2015
  2433                              <1> 	;movzx	ebx, al
  2434                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2435                              <1> 	; 12/01/2022 (BugFix)
  2436 000059CF C0E002              <1> 	shl	al, 2 ; * 4
  2437 000059D2 8B88[52630000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2438                              <1> bwrite_0:
  2439 000059D8 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2440                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2441                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2442 000059D9 8B1D[786D0000]      <1> 	mov	ebx, [u.fofp]
  2443 000059DF 8B03                <1> 	mov	eax, [ebx]       
  2444 000059E1 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2445                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2446 000059E4 39C8                <1> 	cmp	eax, ecx
  2447                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2448                              <1>        	                     ; / block number allowed
  2449                              <1> 	;jnb	error	     ; 18/04/2013
  2450                              <1> 		; bhis error10 / yes, error
  2451                              <1>      	; 08/02/2022
  2452                              <1> 	;jb	short bwrite_1
  2453                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2454                              <1> 	;jmp	error
  2455 000059E6 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2456                              <1> bwrite_1:
  2457                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2458                              <1> 		; inc *u.fofp / no, increment block number
  2459                              <1> 	; 09/06/2015 - 10/07/2015
  2460 000059E8 66833D[D06D0000]00  <1> 	cmp	word [u.pcount], 0
  2461 000059F0 7705                <1> 	ja	short bwrite_2
  2462 000059F2 E8ADF7FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2463                              <1> bwrite_2:
  2464 000059F7 BF[D76D0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2465 000059FC E8C5000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2466                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2467                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2468 00005A01 E815000000          <1>         call	dioreg
  2469                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2470                              <1> 	; esi = destination address (in the buffer)
  2471                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2472                              <1> 	; ecx = transfer count (in bytes)
  2473                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2474 00005A06 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2475 00005A08 F3A4                <1> 	rep	movsb
  2476                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2477                              <1>        		; dec r3 / area to the I/O buffer
  2478                              <1>        		; bne 1b
  2479 00005A0A E8F0000000          <1> 	call	dskwr
  2480                              <1> 		; jsr r0,dskwr / write it out on the device
  2481 00005A0F 59                  <1> 	pop	ecx ; **
  2482 00005A10 833D[8C6D0000]00    <1>         cmp     dword [u.count], 0
  2483                              <1> 		; tst u.count / done
  2484 00005A17 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2485                              <1> 		; beq 1f / yes, 1f
  2486                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2487                              <1>        		; br bwrite / go back and write next block
  2488                              <1> ; 1:
  2489 00005A19 58                  <1> 	pop	eax ; ****
  2490                              <1>        		; mov (sp)+,r0
  2491 00005A1A C3                  <1> 	retn		; 09/06/2015
  2492                              <1>         ;jmp	ret_ 
  2493                              <1> 		; jmp ret / return to routine that called writei
  2494                              <1> ;error10:
  2495                              <1> ;       jmp     error  ; / see 'error' routine
  2496                              <1> 
  2497                              <1> dioreg:
  2498                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2499                              <1> 	; 14/07/2015
  2500                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2501                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2502                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2503                              <1> 	;	
  2504                              <1> 	; bookkeeping on block transfers of data
  2505                              <1> 	;
  2506                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2507                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2508                              <1> 	; 10/07/2015
  2509                              <1> 	; * returns byte offset from beginning of current sector buffer
  2510                              <1> 	; (beginning of data) in ESI
  2511                              <1> 	;
  2512 00005A1B 8B0D[8C6D0000]      <1> 	mov	ecx, [u.count]
  2513                              <1> 		; mov u.count,r3 / move char count to r3
  2514                              <1> 	; 08/02/2022
  2515 00005A21 31D2                <1> 	xor	edx, edx
  2516 00005A23 B602                <1> 	mov	dh, 2
  2517                              <1> 	; edx = 512
  2518 00005A25 39D1                <1> 	cmp	ecx, edx ; 512
  2519                              <1> 	;cmp 	ecx, 512
  2520                              <1> 		; cmp r3,$512. / more than 512. char?
  2521 00005A27 7602                <1> 	jna	short dioreg_0
  2522                              <1> 		; blos 1f / no, branch
  2523 00005A29 89D1                <1> 	mov	ecx, edx ; 512
  2524                              <1> 	;mov	ecx, 512
  2525                              <1> 		; mov $512.,r3 / yes, just take 512.
  2526                              <1> dioreg_0:
  2527                              <1> 	; 09/06/2015
  2528 00005A2B 663B0D[D06D0000]    <1> 	cmp	cx, [u.pcount]
  2529 00005A32 7607                <1> 	jna	short dioreg_1
  2530 00005A34 668B0D[D06D0000]    <1> 	mov	cx, [u.pcount]
  2531                              <1> dioreg_1:
  2532                              <1> ; 1:
  2533 00005A3B 8B15[886D0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2534                              <1> 	        ; mov u.base,r2 / put users base in r2
  2535 00005A41 010D[906D0000]      <1> 	add	[u.nread], ecx
  2536                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2537 00005A47 290D[8C6D0000]      <1> 	sub	[u.count], ecx
  2538                              <1> 		; sub r3,u.count / update count
  2539 00005A4D 010D[886D0000]      <1> 	add	[u.base], ecx
  2540                              <1> 		; add r3,u.base / update base
  2541                              <1> 	; 10/07/2015
  2542                              <1> 	; Retro UNIX 386 v1 - modification !
  2543                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2544                              <1> 	; (It will point to next byte position instead of next block no.)
  2545 00005A53 8B35[786D0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2546 00005A59 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2547 00005A5B 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2548 00005A5D 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2549 00005A62 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2550 00005A64 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2551                              <1> 	; 09/06/2015 - 10/07/2015
  2552 00005A66 66290D[D06D0000]    <1> 	sub	[u.pcount], cx
  2553 00005A6D 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2554 00005A73 8B3D[CC6D0000]      <1> 	mov	edi, [u.pbase]
  2555 00005A79 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2556 00005A7F 01D7                <1> 	add	edi, edx
  2557 00005A81 893D[CC6D0000]      <1> 	mov	[u.pbase], edi
  2558 00005A87 010D[CC6D0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2559 00005A8D C3                  <1> 	retn
  2560                              <1> 		; rts r0 / return
  2561                              <1> 
  2562                              <1> dskrd:
  2563                              <1> 	; 15/07/2022
  2564                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2565                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2566                              <1> 	; 18/08/2015
  2567                              <1> 	; 02/07/2015
  2568                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2569                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2570                              <1> 	;
  2571                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2572                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2573                              <1> 	; (number specified in r1) in the acquired buffer.)
  2574                              <1> 	; If the device is busy at the time dskrd is called,	
  2575                              <1> 	; dskrd calls idle.
  2576                              <1> 	; 
  2577                              <1> 	; INPUTS ->
  2578                              <1> 	;    r1 - block number
  2579                              <1> 	;    cdev - current device number 
  2580                              <1> 	; OUTPUTS ->
  2581                              <1> 	;    r5 - points to first data word in I/O buffer
  2582                              <1> 	;
  2583                              <1> 	; ((AX = R1)) input/output
  2584                              <1> 	; ((BX = R5)) output 
  2585                              <1> 	;
  2586                              <1>         ; ((Modified registers: edx, ecx, ebx, esi, edi))  
  2587                              <1> 	;
  2588 00005A8E E8BA000000          <1> 	call 	bufaloc
  2589                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2590                              <1> 			       ; / get a free I/O buffer
  2591                              <1> 	;;jc	error ; 20/07/2013
  2592 00005A93 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2593                              <1>        		; br 1f / branch if block already in a I/O buffer
  2594                              <1> 	
  2595                              <1> 	; 15/07/2022
  2596                              <1> 	; (buffer header byte 1, bit 2 is disk read bit/flag)
  2597                              <1> dskrd_0:
  2598                              <1> 	; 10/07/2015 (wslot)
  2599 00005A95 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2600                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2601                              <1> 		               ; / I/O queue entry for buffer
  2602 00005A9A E893000000          <1> 	call	poke
  2603                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2604                              <1> 			    ; /	bit 10=1 says read
  2605                              <1> 	; 09/06/2015
  2606                              <1> 	;jnc	short dskrd_1
  2607                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2608                              <1> 	;jmp	error
  2609                              <1> 	; 08/02/2022
  2610 00005A9F 7204                <1> 	jc	short dskrd_3
  2611                              <1> dskrd_1: ; 1:
  2612                              <1>        	; 15/07/2022
  2613                              <1> 	;
  2614                              <1> 	;	;clr *$ps
  2615                              <1>        	;test	word [ebx], 2400h
  2616                              <1> 	;	; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2617                              <1> 	;			; / jump to idle
  2618                              <1>        	;jz	short dskrd_2
  2619                              <1> 	;	; beq 1f
  2620                              <1>         ;;;mov   ecx, [s.wait_]
  2621                              <1>        	;call	idle
  2622                              <1> 	;	; jsr r0,idle; s.wait+2
  2623                              <1> 	;jmp 	short dskrd_1
  2624                              <1>        	;	; br 1b
  2625                              <1> dskrd_2: ; 1:
  2626 00005AA1 83C308              <1>         add	ebx, 8
  2627                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2628                              <1> 			  ; / just read in
  2629 00005AA4 C3                  <1>        	retn
  2630                              <1> 		; rts r0
  2631                              <1> dskrd_err: 
  2632                              <1> 	; 08/02/2022
  2633                              <1> 	; (jump from 'bread' error)	
  2634                              <1> dskrd_3:	
  2635                              <1> 	; 08/02/2022
  2636 00005AA5 803D[D76D0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2637 00005AAC 7509                <1> 	jne	short dskrd_4 ; no
  2638                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2639 00005AAE C605[D76D0000]00    <1> 	mov	byte [u.brwdev], 0
  2640 00005AB5 EB0A                <1> 	jmp	short dskrd_5
  2641                              <1> dskrd_4:
  2642 00005AB7 C705[D86D0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2642 00005ABF 0000                <1>
  2643                              <1> dskrd_5:
  2644 00005AC1 E9A7D7FFFF          <1> 	jmp	error
  2645                              <1> 
  2646                              <1> bwslot:
  2647                              <1> 	; 15/07/2022
  2648                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2649                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2650                              <1> 	; 10/07/2015
  2651                              <1> 	;	If the block/sector is not placed in a buffer
  2652                              <1> 	;	before 'wslot', it must be read before
  2653                              <1> 	;	it is written! (Otherwise transfer counts less
  2654                              <1> 	;	than 512 bytes will be able to destroy existing 
  2655                              <1> 	;	data on disk.)
  2656                              <1> 	;
  2657                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2658                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2659                              <1> 	; Retro UNIX 8086 v1 modification !
  2660                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2661                              <1> 	; INPUT -> EDI - points to device id (in u.brwdev)	
  2662                              <1> 	;	-> EAX = block number
  2663                              <1> 	;
  2664 00005AC6 E88F000000          <1> 	call	bufaloc_0
  2665 00005ACB 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2666                              <1> 	; 12/01/2022
  2667                              <1> 	; ebx = buffer header address
  2668                              <1> bwslot_0:
  2669                              <1> 	; 10/07/2015
  2670 00005ACD 8B35[786D0000]      <1> 	mov	esi, [u.fofp]
  2671 00005AD3 8B06                <1> 	mov	eax, [esi]
  2672 00005AD5 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2673 00005ADA 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2674                              <1> 		       ; recent disk data must be placed in the buffer
  2675 00005ADC 813D[8C6D0000]0002- <1> 	cmp	dword [u.count], 512
  2675 00005AE4 0000                <1>
  2676 00005AE6 730F                <1> 	jnb	short wslot_0	
  2677                              <1> bwslot_1:
  2678 00005AE8 E8A8FFFFFF          <1> 	call	dskrd_0
  2679                              <1> 	; 12/01/2022
  2680                              <1> 	; ebx = buffer data address = buffer header addr + 8
  2681 00005AED 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again	
  2682 00005AF0 EB05                <1> 	jmp 	short wslot_0
  2683                              <1> 
  2684                              <1> wslot:
  2685                              <1> 	; 16/07/2022
  2686                              <1> 	; 15/07/2022
  2687                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2688                              <1> 	;
  2689                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2690                              <1> 	; 		(32 bit modifications)
  2691                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2692                              <1> 	;
  2693                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2694                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2695                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2696                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2697                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2698                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2699                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2700                              <1> 	;
  2701                              <1> 	; INPUTS ->
  2702                              <1>  	;    r1 - block number
  2703                              <1> 	;    cdev - current (block/disk) device number
  2704                              <1>  	;
  2705                              <1> 	; OUTPUTS ->
  2706                              <1> 	;    bufp - bits 9 and 15 are set, 
  2707                              <1> 	;           the remainder of the word left unchanged
  2708                              <1> 	;    r5 - points to first data word in I/O buffer
  2709                              <1> 	;
  2710                              <1> 	; ((AX = R1)) input/output
  2711                              <1> 	; ((BX = R5)) output 
  2712                              <1> 	;
  2713                              <1>         ; ((Modified registers: edx, ecx, ebx, esi, edi)) 
  2714                              <1> 
  2715 00005AF2 E856000000          <1> 	call	bufaloc
  2716                              <1> 	; 10/07/2015
  2717                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2718                              <1>         	; br 1f / word in buffer in r5
  2719                              <1> 	; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2720                              <1>         ; EAX = Block/Sector number (r1)
  2721                              <1> wslot_0: ;1:
  2722                              <1> 	; 15/07/2022
  2723                              <1> 	;
  2724                              <1>      	;test	word [ebx], 2400h
  2725                              <1> 	;	; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2726                              <1> 	;			; / of I/O queue entry
  2727                              <1> 	;jz	short wslot_1
  2728                              <1>         ;       ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2729                              <1> 	;	       ; / or not waiting to read)
  2730                              <1> 	;
  2731                              <1> 	;;mov	ecx, [s.wait_] ; 29/07/2013
  2732                              <1> 	;call	idle
  2733                              <1> 	;	; jsr r0,idle; / if buffer is reading or writing to read,
  2734                              <1>        	;                   ; / idle
  2735                              <1> 	;jmp	short wslot_0
  2736                              <1> 	;	; br 1b / till finished
  2737                              <1> wslot_1: ;1:
  2738                              <1> 	;or	word [ebx], 8200h
  2739                              <1>        	;	; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2740                              <1>         ;			; / (write, inhibit bits)
  2741                              <1> 	;	; clr *$ps / clear processor status
  2742                              <1> 
  2743                              <1> 	; 16/07/2022
  2744                              <1> ;dskwr_1:	; 09/03/2022
  2745                              <1> 	;add	ebx, 8 ; 11/06/2015
  2746                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2747                              <1> 			  ; / for this block
  2748                              <1> 	; 15/07/2022
  2749                              <1> 	; (set disk write bit/flag)
  2750                              <1> 	;or	word [ebx], 200h	
  2751 00005AF7 43                  <1> 	inc	ebx
  2752 00005AF8 800B02              <1> 	or	byte [ebx], 2
  2753 00005AFB 83C307              <1> 	add	ebx, 7
  2754                              <1> 	; 16/07/2022
  2755                              <1> dskwr_1:	; 08/02/2022
  2756 00005AFE C3                  <1>        	retn
  2757                              <1> 		; rts r0
  2758                              <1> dskwr:
  2759                              <1> 	; 16/07/2022
  2760                              <1> 	; 15/07/2022
  2761                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2762                              <1> 	; 09/03/2022
  2763                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2764                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2765                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2766                              <1> 	;
  2767                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2768                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2769                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2770                              <1> 	; previously has supplied all the information required in the
  2771                              <1> 	; I/O queue entry.
  2772                              <1> 	;
  2773                              <1> 	; (Modified registers: ebx, ecx, edx, esi, edi)
  2774                              <1> 	;
  2775 00005AFF 8B1D[F46C0000]      <1> 	mov	ebx, [bufp]
  2776 00005B05 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2777                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2778                              <1>                                   ; / bottom of queue
  2779 00005B0A E823000000          <1> 	call	poke
  2780                              <1> 	; 09/06/2015
  2781 00005B0F 73ED                <1> 	jnc	short dskwr_1 ; 16/07/2022
  2782                              <1> 	; ebx = buffer header ; 09/03/2022
  2783                              <1> 	; 08/02/2022
  2784 00005B11 803D[D76D0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2785 00005B18 7509                <1> 	jne	short dskwr_0 ; no
  2786                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2787 00005B1A C605[D76D0000]00    <1> 	mov	byte [u.brwdev], 0
  2788 00005B21 EB0A                <1> 	jmp	short dskwr_2
  2789                              <1> dskwr_0:
  2790 00005B23 C705[D86D0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2790 00005B2B 0000                <1>
  2791                              <1> dskwr_2:
  2792 00005B2D E93BD7FFFF          <1> 	jmp	error
  2793                              <1> ;dskwr_1:
  2794                              <1> ;	add	ebx, 8 ; 09/03/2022
  2795                              <1> ;	; ebx = buffer data address
  2796                              <1> ;	retn
  2797                              <1> 
  2798                              <1> ;ppoke:
  2799                              <1>        		; mov $340,*$ps
  2800                              <1>        		; jsr r0,poke
  2801                              <1>        		; clr *$ps
  2802                              <1> 		; rts r0
  2803                              <1> 
  2804                              <1> poke:
  2805                              <1> 	; 15/07/2022
  2806                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  2807                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2808                              <1> 	; 14/07/2022
  2809                              <1> 	;	! Major Modification !
  2810                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2811                              <1> 	;
  2812                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2813                              <1> 	; 24/10/2015
  2814                              <1> 	; 20/08/2015
  2815                              <1> 	; 18/08/2015
  2816                              <1> 	; 02/07/2015
  2817                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2818                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2819                              <1> 	;
  2820                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2821                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2822                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2823                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2824                              <1> 	;
  2825                              <1> 	; Basic I/O functions for all block structured devices
  2826                              <1> 	;
  2827                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2828                              <1> 	;
  2829                              <1> 	; 20/07/2013 modifications
  2830                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2831                              <1> 	; INPUTS -> 
  2832                              <1> 	;        EBX = buffer header address
  2833                              <1> 	; OUTPUTS ->
  2834                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2835                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2836                              <1> 	;		(drive not ready or r/w error!)
  2837                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2838                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2839                              <1> 	;        (also it indicates invalid buffer data)
  2840                              <1> 	
  2841                              <1> 	; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2842                              <1> 	; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2843                              <1> 	; Buffer header:
  2844                              <1> 	;	byte 0 - device/disk (index) number
  2845                              <1> 	;	byte 1 - status
  2846                              <1> 	;	    before 'poke'	
  2847                              <1> 	;		bit 0 - valid bit 
  2848                              <1> 	;		   (0 for new buffer)
  2849                              <1> 	;		   (1 for existing buffer)	
  2850                              <1> 	;		bit 1 - write (modified) bit, disk write flag
  2851                              <1> 	;		bit 2 - read bit, disk read flag
  2852                              <1> 	;	    after 'poke'
  2853                              <1> 	;		if disk r/w is successed
  2854                              <1> 	;		   bit 0 = 1
  2855                              <1> 	;		   bit 1 = 0
  2856                              <1> 	;		   bit 2 = 0
  2857                              <1> 	;		if disk r/w is failed
  2858                              <1> 	;		   bit 0 = 0 (invalid buffer)
  2859                              <1> 	;		   bit 1 = 0 (write bit)
  2860                              <1> 	;		   bit 2 = 0 (read bit)	
  2861                              <1>  	;
  2862                              <1> 	;	byte 2 & byte 3 - not used
  2863                              <1> 	;	byte 4 to byte 7 - disk block/sector address
  2864                              <1> 	
  2865                              <1> 	; 04/02/2022
  2866 00005B32 50                  <1> 	push	eax
  2867 00005B33 E896000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2868 00005B38 58                  <1> 	pop	eax
  2869 00005B39 730D                <1> 	jnc	short seta ; 14/07/2022
  2870                              <1> 	
  2871                              <1> 	; 14/07/2022
  2872                              <1> 	; (invalidate buffer)
  2873                              <1> 	
  2874                              <1> 	; 02/07/2015 (32 bit modification)
  2875                              <1> 	; 20/07/2013
  2876 00005B3B C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2877                              <1>        		; mov $-1,2(r1) / destroy associativity
  2878 00005B42 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2879                              <1> 		; clrb 1(r1) / do not do I/O
  2880                              <1> 	;stc
  2881 00005B47 C3                  <1> 	retn
  2882                              <1>         	; rts r0
  2883                              <1> seta: 
  2884 00005B48 C6430101            <1> 	mov	byte [ebx+1], 1 ; clear write/read bits, set valid bit
  2885                              <1> 	;clc
  2886 00005B4C C3                  <1> 	retn
  2887                              <1> 
  2888                              <1> %if 0
  2889                              <1> 
  2890                              <1> poke:
  2891                              <1> 	; 29/11/2021 (32 bit reg push-pop)
  2892                              <1> 	; 24/10/2015
  2893                              <1> 	; 20/08/2015
  2894                              <1> 	; 18/08/2015
  2895                              <1> 	; 02/07/2015
  2896                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2897                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2898                              <1> 	;
  2899                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2900                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2901                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2902                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2903                              <1> 	;
  2904                              <1> 	; Basic I/O functions for all block structured devices
  2905                              <1> 	;
  2906                              <1>         ; (Modified registers: ecx, edx, esi, edi)
  2907                              <1> 	;
  2908                              <1> 	; 20/07/2013 modifications
  2909                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2910                              <1> 	; INPUTS -> 
  2911                              <1> 	;        (EBX = buffer header address)
  2912                              <1> 	; OUTPUTS ->
  2913                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2914                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2915                              <1> 	;		(drive not ready or r/w error!)
  2916                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2917                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2918                              <1> 	;        (also it indicates invalid buffer data)
  2919                              <1> 	;
  2920                              <1> 	push	ebx
  2921                              <1>        		; mov r1,-(sp)
  2922                              <1>        		; mov r2,-(sp)
  2923                              <1>        		; mov r3,-(sp)
  2924                              <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2925                              <1> 	;
  2926                              <1> 	; 09/06/2015
  2927                              <1> 	; (permit read/write after a disk R/W error)
  2928                              <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2929                              <1> 	mov	al, 1
  2930                              <1> 	shl	al, cl
  2931                              <1> 	test 	al, [active] ; busy ? (error)
  2932                              <1> 	jz	short poke_0
  2933                              <1> 	not	al
  2934                              <1> 	and	[active], al ; reset busy bit for this device only
  2935                              <1> poke_0:
  2936                              <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2937                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2938                              <1> 					 ; / I/O queue pointer
  2939                              <1> poke_1: ; 1:
  2940                              <1>         sub	esi, 4
  2941                              <1> 	mov	ebx, [esi]
  2942                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2943                              <1> 	mov	ax, [ebx] ; 17/07/2013
  2944                              <1>        	test	ah, 06h
  2945                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2946                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2947                              <1> 			       ; / queue entry
  2948                              <1>         jz      short poke_5
  2949                              <1> 		; beq 2f / branch to 2f if both are clear
  2950                              <1> 	; 31/07/2013
  2951                              <1> 	;test	ah, 0B0h ; (*)
  2952                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2953                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2954                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2955                              <1> 		; bne 2f / branch if any are set
  2956                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2957                              <1>     		; movb (r1),r3 / get device id
  2958                              <1> 	movzx	ecx, al ; 18/08/2015
  2959                              <1> 	;mov	edi, ecx ; 26/04/2013
  2960                              <1> 	xor 	eax, eax ; 0
  2961                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2962                              <1> 		; tstb deverr(r3) / test for errors on this device
  2963                              <1>        	;jna	short poke_2 
  2964                              <1> 		; beq 3f / branch if no errors
  2965                              <1> 	; 02/07/2015
  2966                              <1> 	;dec	eax
  2967                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2968                              <1>        		; mov $-1,2(r1) / destroy associativity
  2969                              <1> 	;shr	eax, 24
  2970                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2971                              <1> 		; clrb 1(r1) / do not do I/O
  2972                              <1> 	;jmp	short poke_5
  2973                              <1>         ;       ; br 2f
  2974                              <1>                 ; rts r0
  2975                              <1> poke_2: ; 3:
  2976                              <1> 	; 02/07/2015
  2977                              <1> 	inc	cl ; 0FFh -> 0
  2978                              <1> 	jz	short poke_5
  2979                              <1> 	inc	al ; mov ax, 1
  2980                              <1> 	dec	cl
  2981                              <1> 	jz	short poke_3
  2982                              <1> 	; 26/04/2013 Modification
  2983                              <1> 	;inc	al ; mov ax, 1
  2984                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2985                              <1> 	;jz	short poke_3 ; cl = 0
  2986                              <1> 	shl	al, cl ; shl ax, cl
  2987                              <1> poke_3:
  2988                              <1> 	;test	[active], ax
  2989                              <1> 	test	[active], al
  2990                              <1> 		; bit $2,active / test disk busy bit
  2991                              <1> 	jnz     short poke_5
  2992                              <1> 		; bne 2f / branch if bit is set
  2993                              <1> 	;or	[active], ax
  2994                              <1> 	or	[active], al
  2995                              <1> 		; bis $2,active / set disk busy bit
  2996                              <1> 	push	eax ; 29/11/2021
  2997                              <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2998                              <1> 	;mov    [edi+drv.error], ah
  2999                              <1> 	pop	eax
  3000                              <1> 	jnc	short poke_4 ; 20/07/2013
  3001                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  3002                              <1> 	;jna	short poke_4
  3003                              <1> 		; tstb deverr(r3) / test for errors on this device
  3004                              <1>        		; beq 3f / branch if no errors
  3005                              <1> 	; 02/07/2015 (32 bit modification)
  3006                              <1> 	; 20/07/2013
  3007                              <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  3008                              <1>        		; mov $-1,2(r1) / destroy associativity
  3009                              <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  3010                              <1> 		; clrb 1(r1) / do not do I/O
  3011                              <1> 	jmp     short poke_5
  3012                              <1> poke_4:	; 20/07/2013
  3013                              <1> 	; 17/07/2013
  3014                              <1> 	not 	al 
  3015                              <1> 	and	[active], al ; reset, not busy
  3016                              <1> 	; EBX = system I/O buffer header (queue entry) address
  3017                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  3018                              <1> 	mov	ax, [ebx]
  3019                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  3020                              <1>         and	ax, 600h
  3021                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  3022                              <1> 	and 	word [ebx], 0F9FFh
  3023                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  3024                              <1> 	shl	ah, 3
  3025                              <1>        		; rol r3
  3026                              <1>                 ; rol r3
  3027                              <1>                 ; rol r3	
  3028                              <1> 	or	[ebx], ax
  3029                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  3030                              <1> 			   ; bits 12 and 13
  3031                              <1> 	call	idle ; 18/01/2014
  3032                              <1> 	;; sti
  3033                              <1> 	;hlt 	; wait for a hardware interrupt
  3034                              <1> 	;; cli
  3035                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  3036                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  3037                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  3038                              <1> 	; method, this procedure will wait for a time according to
  3039                              <1> 	; multi tasking and time sharing concept.
  3040                              <1> 	;
  3041                              <1> 	; 24/10/2015
  3042                              <1> 	;not	ax 
  3043                              <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  3044                              <1> 	and	[ebx], ax ; clear bits 12 and 13
  3045                              <1> poke_5: ;2:
  3046                              <1>         cmp     esi, bufp
  3047                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  3048                              <1>                             ; / has been scanned
  3049                              <1> 	ja      short poke_1
  3050                              <1> 		; bhi 1b
  3051                              <1> 	; 24/03/2013
  3052                              <1>        		; mov (sp)+,r3
  3053                              <1>        		; mov (sp)+,r2
  3054                              <1>        		; mov (sp)+,r1
  3055                              <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  3056                              <1> 	pop 	ebx
  3057                              <1> 	; 02/07/2015 (32 bit modification)
  3058                              <1> 	; 20/07/2013
  3059                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  3060                              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  3061                              <1> 	;	
  3062                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  3063                              <1> 	; or written successfully; even if an error occurs while
  3064                              <1> 	; reading to or writing from other buffers. 20/07/2013
  3065                              <1> 	;
  3066                              <1> 	; 09/06/2015
  3067                              <1> 	cmc
  3068                              <1> 	retn
  3069                              <1>                 ; rts r0
  3070                              <1> 
  3071                              <1> %endif
  3072                              <1> 
  3073                              <1> bufaloc:
  3074                              <1> 	; 15/07/2022
  3075                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  3076                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3077                              <1> 	; 20/08/2015
  3078                              <1> 	; 19/08/2015
  3079                              <1> 	; 02/07/2015
  3080                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3081                              <1> 	;	     (32 bit modifications)	
  3082                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  3083                              <1> 	;
  3084                              <1> 	; bufaloc - Block device I/O buffer allocation
  3085                              <1> 	; 
  3086                              <1> 	; INPUTS ->
  3087                              <1> 	;    r1 - block number
  3088                              <1> 	;    cdev - current (block/disk) device number
  3089                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  3090                              <1> 	; OUTPUTS ->
  3091                              <1> 	;    r5 - pointer to buffer allocated
  3092                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  3093                              <1> 	;
  3094                              <1> 	; ((AX = R1)) input/output
  3095                              <1> 	; ((BX = R5)) output
  3096                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  3097                              <1> 	;    zf=1 -> block already in a I/O buffer
  3098                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  3099                              <1> 	;    ((DL = Device ID))
  3100                              <1> 	;    (((DH = 0 or 1)))
  3101                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  3102                              <1> 	;    ((CX and DH will not be used after return)))
  3103                              <1> 
  3104                              <1> 	; 15/07/2022
  3105                              <1> 	;	Modified registers: EBX, ECX, EDX, ESI, EDI
  3106                              <1> 
  3107                              <1> 	;;push 	esi ; ***
  3108                              <1> 		; mov r2,-(sp) / save r2 on stack
  3109                              <1>        		; mov $340,*$ps / set processor priority to 7
  3110                              <1> 	; 20/07/2013
  3111                              <1> 	; 26/04/2013
  3112                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  3113                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  3114                              <1> 	;add	edi, ebx
  3115                              <1> 	; 09/01/2022
  3116 00005B4D 0FB63D[416D0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  3117 00005B54 81C7[426D0000]      <1> 	add	edi, rdev
  3118                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  3119                              <1> 			;; EDI points to device id.
  3120 00005B5A 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  3121                              <1> 	; 11/06/2021
  3122 00005B5D 80BB[6E630000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  3123 00005B64 720F                <1> 	jb	short bufaloc_9
  3124 00005B66 C705[D86D0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3124 00005B6E 0000                <1>
  3125 00005B70 E9F8D6FFFF          <1> 	jmp	error
  3126                              <1> bufaloc_9:
  3127 00005B75 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  3128                              <1> bufaloc_10: ; 02/07/2015
  3129                              <1> 	; 14/07/2022
  3130                              <1> 	;xor 	ebp, ebp ; 0
  3131                              <1> 	;push	ebp ; 0
  3132                              <1>         ;mov	ebp, esp
  3133 00005B77 31FF                <1> 	xor	edi, edi ; 0
  3134 00005B79 57                  <1> 	push	edi
  3135                              <1> bufaloc_1: ;1:
  3136                              <1> 		; clr -(sp) / vacant buffer
  3137 00005B7A BE[F46C0000]        <1>         mov 	esi, bufp
  3138                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3139                              <1> 			     ; / entrys in buffer area
  3140                              <1> bufaloc_2: ;2:
  3141 00005B7F 8B1E                <1> 	mov	ebx, [esi]
  3142                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3143                              <1> 			    ; queue entry into r5
  3144                              <1> 	; 15/07/2022
  3145 00005B81 8B0B                <1> 	mov	ecx, [ebx]	
  3146                              <1> 	;test	word [ebx], 0F600h
  3147                              <1> 	; 15/07/2022
  3148 00005B83 F6C501              <1> 	test	ch, 1 ; valid buffer (content) ?
  3149                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3150 00005B86 7505                <1>         jnz	short bufaloc_3 ; yes
  3151                              <1> 		; bne 3f / branch when 
  3152                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3153                              <1>                        ; / (i.e., buffer busy)
  3154                              <1> 	;mov    [ebp], esi ; pointer to I/0 queue entry
  3155                              <1> 	; 15/07/2022
  3156                              <1> 	; save free buffer pointer 
  3157 00005B88 893424              <1> 	mov	[esp], esi
  3158                              <1>                 ; mov r2,(sp) ;/ save pointer to last non-busy buffer
  3159                              <1> 			; / found points to word 2 of I/O queue entry)
  3160                              <1> 	; continue to see if requested sector/block buffer
  3161                              <1> 	;	already is one of existing (valid) buffers
  3162                              <1> 	;jmp	short bufaloc_4
  3163 00005B8B EB0E                <1> 	jmp	short bufaloc_11 ; 15/07/2022
  3164                              <1> bufaloc_3: ;3:
  3165                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3166                              <1> 	;
  3167 00005B8D 38D1                <1> 	cmp	cl, dl ; 15/07/2022
  3168                              <1> 	;cmp	[ebx], dl	
  3169                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3170                              <1> 			       ; / as current device
  3171 00005B8F 7508                <1> 	jne	short bufaloc_4
  3172                              <1>        		; bne 3f
  3173 00005B91 394304              <1> 	cmp	[ebx+4], eax
  3174                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3175                              <1> 			     ; / same as current block number
  3176 00005B94 7503                <1>        	jne	short bufaloc_4
  3177                              <1> 		; bne 3f
  3178                              <1> 	;add	esp, 4
  3179 00005B96 59                  <1> 	pop	ecx
  3180                              <1>        		; tst (sp)+ / bump stack pointer
  3181 00005B97 EB1D                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3182                              <1> 				; jump to bufaloc_6 in original Unix v1
  3183                              <1>        		; br 1f / use this buffer
  3184                              <1> bufaloc_4: ;3:
  3185                              <1> 	; 15/07/2022
  3186                              <1> 	; save last valid buffer 
  3187                              <1> 	; (will be used if there is not a free buffer)
  3188 00005B99 89F7                <1> 	mov	edi, esi	
  3189                              <1> bufaloc_11:
  3190 00005B9B 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3191                              <1> 	;
  3192 00005B9E 81FE[346D0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3193                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3194 00005BA4 72D9                <1> 	jb	short bufaloc_2
  3195                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3196                              <1>                        ; / buffers not checked)
  3197 00005BA6 5E                  <1>         pop	esi
  3198                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3199                              <1> 			     ; / to last free block
  3200 00005BA7 09F6                <1>        	or	esi, esi 
  3201 00005BA9 7502                <1> 	jnz	short bufaloc_5
  3202                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3203                              <1> 	        ; / if a free buffer is found branch to 2f
  3204                              <1> 
  3205                              <1> 	; 15/07/2022        
  3206                              <1> 	; if there is not a free buffer
  3207                              <1> 	; we can use last valid buffer (the oldest buffer)
  3208                              <1> 	; ((ptr to new buffer is located at head of buff ptr chain))
  3209 00005BAB 89FE                <1> 	mov	esi, edi
  3210                              <1> 
  3211                              <1> 	;;mov  ecx, [s.wait_]
  3212                              <1> 	;call	idle
  3213                              <1> 	;	; jsr r0,idle; s.wait+2 / idle if no free buffers
  3214                              <1> 	;jmp 	short bufaloc_10 ; 02/07/2015
  3215                              <1>        	;	; br 1b
  3216                              <1> bufaloc_5: ;2:
  3217                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3218                              <1> 	; 15/07/2022
  3219                              <1> 	;inc	dh ; Retro UNIX 8086 v1 modification
  3220                              <1> bufaloc_6: ;1:
  3221 00005BAD 8B1E                <1>         mov    	ebx, [esi] 
  3222                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3223                              <1> 			     ; / entry in r5
  3224                              <1> 	;; 26/04/2013
  3225                              <1>         ;;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3226                              <1> 	;mov 	[ebx], dl
  3227                              <1> 		; movb cdev,(r5) / put current device number 
  3228                              <1> 				 ; / in I/O queue entry
  3229                              <1> 	; 15/07/2022
  3230                              <1> 	; invalidate buffer before r/w (new) disk sector/block
  3231                              <1> 	;mov	[ebx+1], dh ; 0
  3232                              <1> 	; 15/07/2022
  3233 00005BAF 8913                <1> 	mov	[ebx], edx  ; dh = 0
  3234                              <1> 	
  3235 00005BB1 894304              <1> 	mov 	[ebx+4], eax
  3236                              <1> 		; mov r1,2(r5) / move block number into word 2
  3237                              <1> 			     ; / of I/O queue entry
  3238                              <1> 	; 15/07/2022
  3239 00005BB4 FEC6                <1> 	inc	dh ; dh = 1
  3240                              <1> bufaloc_7: ;1:
  3241 00005BB6 81FE[F46C0000]      <1>         cmp	esi, bufp
  3242                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3243                              <1> 			     ; / and put latest assigned
  3244 00005BBC 760B                <1> 	jna	short bufaloc_8	
  3245                              <1>        		; blos 1f / buffer on the top 
  3246                              <1> 			; / (this makes if the lowest priority)
  3247                              <1> 	; 15/07/2022
  3248 00005BBE 89F7                <1> 	mov	edi, esi
  3249 00005BC0 83EE04              <1> 	sub	esi, 4
  3250 00005BC3 8B0E                <1> 	mov	ecx, [esi]
  3251 00005BC5 890F                <1> 	mov	[edi], ecx ; 15/07/2022
  3252                              <1> 	;mov	[esi+4], ecx
  3253                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3254 00005BC7 EBED                <1> 	jmp 	short bufaloc_7
  3255                              <1> 		; br 1b
  3256                              <1> bufaloc_8: ;1:
  3257 00005BC9 891E                <1>         mov	[esi], ebx
  3258                              <1> 		; mov r5,(r2)
  3259                              <1> 	;;pop	esi ; ***
  3260                              <1>        		; mov (sp)+,r2 / restore r2
  3261 00005BCB 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3262                              <1> 		; Retro UNIX 8086 v1 modification
  3263                              <1> 		; zf=1 --> block already is in an I/O buffer
  3264                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3265 00005BCD C3                  <1> 	retn
  3266                              <1> 		; rts r0
  3267                              <1> 
  3268                              <1> diskio:
  3269                              <1> 	; 16/07/2022
  3270                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  3271                              <1> 	; 08/07/2022
  3272                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3273                              <1> 	;	((simplified and shortened 'diskio.s' code))
  3274                              <1> 	; 12/02/2022
  3275                              <1> 	; 10/02/2022
  3276                              <1> 	; 08/02/2022
  3277                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3278                              <1> 	; 28/11/2021
  3279                              <1> 	; 10/07/2015
  3280                              <1> 	; 02/07/2015
  3281                              <1> 	; 16/06/2015
  3282                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3283                              <1> 	;	     (80386 protected mode modifications)	
  3284                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3285                              <1> 	;
  3286                              <1> 	; Retro UNIX 8086 v1 feature only !
  3287                              <1> 	;
  3288                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3289                              <1> 	; 04/07/2009 - 20/07/2011
  3290                              <1> 	;
  3291                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3292                              <1> 	;
  3293                              <1>         ; INPUTS ->
  3294                              <1> 	; 	   ebx = System I/O Buffer header address
  3295                              <1> 	;
  3296                              <1>         ; OUTPUTS -> cf=0 --> done 
  3297                              <1> 	; 	     cf=1 --> error code in AH
  3298                              <1> 	;	     ; 08/02/2022
  3299                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3300                              <1> 	;		error code in [u.error]
  3301                              <1> 	;		
  3302                              <1> 	; (Modified registers: eax, ecx, edx)
  3303                              <1> 	
  3304                              <1> ;rw_disk_sector:
  3305                              <1> 	; 16/07/2022
  3306                              <1> 	; 12/07/2022
  3307                              <1> 	;	Retro UNIX 386 v1.2 (Kernel v0.2.2.3)
  3308                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3309                              <1> 	; 12/02/2022
  3310                              <1> 	; 10/02/2022
  3311                              <1> 	; 08/02/2022
  3312                              <1> 	; 28/11/2021
  3313                              <1> 	; 10/07/2015
  3314                              <1> 	; 02/07/2015
  3315                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3316                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3317                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3318                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3319                              <1> 	;
  3320                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3321                              <1> 	;mov	dh, 2
  3322                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3323 00005BCE B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3324 00005BD0 668B03              <1> 	mov	ax, [ebx] 
  3325                              <1> 	;
  3326 00005BD3 56                  <1> 	push	esi ; ****
  3327 00005BD4 53                  <1> 	push	ebx ; ***
  3328                              <1> 	;
  3329 00005BD5 0FB6C8              <1> 	movzx	ecx, al
  3330                              <1> 	; 28/11/2021
  3331                              <1> 	;mov	ecx, eax
  3332 00005BD8 89CE                <1> 	mov	esi, ecx
  3333                              <1> 	;
  3334 00005BDA 38F1                <1> 	cmp	cl, dh ; 2
  3335 00005BDC 7202                <1> 	jb	short rwdsk0
  3336 00005BDE 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3337                              <1> rwdsk0:
  3338                              <1> 	; 16/07/2022
  3339                              <1> 	; 12/07/2022
  3340                              <1> 	;mov	[drv], al
  3341 00005BE0 81C6[6E630000]      <1> 	add	esi, drv.status
  3342                              <1> 	; 11/06/2015
  3343 00005BE6 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3344 00005BE9 7204                <1> 	jb      short rwdsk1
  3345                              <1> 	; 'drive not ready' error
  3346                              <1> 	; 10/02/2022
  3347                              <1> 	; 08/02/2022
  3348                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3349                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3350                              <1> 	;;jmp	error
  3351                              <1> 	;stc	; cf = 1
  3352                              <1> 	;retn
  3353                              <1> 	; 10/02/2022
  3354 00005BEB B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3355 00005BED EB1F                <1> 	jmp	short rwdsk_err1
  3356                              <1> rwdsk1:
  3357                              <1> 	; 16/07/2022
  3358                              <1> 	;test	ah, 2
  3359                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3360                              <1> 	;		 ; write bit
  3361                              <1> 	;jz	short rwdsk2
  3362                              <1> 	
  3363                              <1> 	;;test	ah, 4
  3364                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3365                              <1> 	;;		 ; read bit
  3366                              <1> 	;;jz	short diskio_ret
  3367                              <1> 
  3368                              <1> 	;inc	dh ; 03h = write
  3369                              <1> 
  3370                              <1> 	; 08/07/2022
  3371 00005BEF 84F4                <1> 	test	ah, dh ; test ah, 2
  3372 00005BF1 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3373 00005BF3 FECE                <1> 	dec	dh
  3374                              <1> 		; dh = 01h = read
  3375                              <1> rwdsk2:
  3376 00005BF5 88C2                <1> 	mov	dl, al
  3377 00005BF7 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3378 00005BFA 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3379 00005BFC C0E102              <1> 	shl	cl, 2
  3380 00005BFF 81C1[52630000]      <1> 	add	ecx, drv.size ; disk size
  3381 00005C05 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3382 00005C07 7214                <1> 	jb      short rwdsk3
  3383                              <1>  	; 'out of volume' error
  3384                              <1> 	; 10/02/2022
  3385                              <1> 	; 08/02/2022
  3386                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3387                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3388                              <1> 	;;jmp	error
  3389                              <1> 	;stc	; cf = 1
  3390                              <1> 	;retn
  3391                              <1> 	; 10/02/2022
  3392 00005C09 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3393                              <1> rwdsk_err1:
  3394 00005C0E C605[D76D0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3395 00005C15 890D[D86D0000]      <1> 	mov	[u.error], ecx ; 12/02/2022
  3396 00005C1B EB27                <1> 	jmp	short rwdsk_err2
  3397                              <1> rwdsk3:
  3398                              <1> 	; 11/06/2015
  3399 00005C1D 83C304              <1> 	add	ebx, 4 ; buffer address
  3400 00005C20 C605[FB6D0000]04    <1> 	mov	byte [retry_count], 4
  3401                              <1> 	; 12/07/2022
  3402                              <1> 	;test	byte [esi], 1 ; LBA ready ?
  3403                              <1>         ;jz	short rwdsk_chs
  3404                              <1> rwdsk_lba:
  3405                              <1> 	; LBA read/write (with private LBA function) 
  3406                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3407 00005C27 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3408 00005C2A 89C1                <1> 	mov	ecx, eax ; sector number
  3409                              <1> 	; ebx = buffer (data) address
  3410                              <1> 	; dl = physical drive number (0, 1, 80h, 81h, 82h, 83h)
  3411                              <1> rwdsk_lba_retry:
  3412                              <1> 	;mov	dl, [drv]
  3413                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3414                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3415                              <1> 	;;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3416                              <1> 	;mov	ah, 2 ; LBA write function number - 2
  3417                              <1> 	;add	ah, dh		
  3418                              <1> 	;mov	al, 1
  3419                              <1> 	;int	13h
  3420                              <1> 	;call	int13h
  3421                              <1> 	; 12/07/2022
  3422 00005C2C 88F0                <1> 	mov	al, dh	; function (1 or 2)
  3423                              <1> 			; (1 = read, 2 = write )
  3424                              <1> 	; ecx = disk sector address (LBA)
  3425                              <1> 	; ebx = buffer address
  3426                              <1> 	;  dl = (physical) disk number
  3427                              <1> 	;  al = function (r/w)
  3428 00005C2E E837C4FFFF          <1> 	call	DISK_IO
  3429                              <1> 
  3430 00005C33 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3431 00005C35 730E                <1> 	jnc	short rwdsk_lba_ok
  3432 00005C37 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3433 00005C3A 7408                <1>         je      short rwdsk_lba_fails
  3434 00005C3C FE0D[FB6D0000]      <1> 	dec	byte [retry_count]
  3435 00005C42 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3436                              <1> rwdsk_err2:	; 10/02/2022
  3437                              <1> rwdsk_lba_fails:
  3438 00005C44 F9                  <1> 	stc
  3439                              <1> rwdsk_lba_ok:
  3440 00005C45 5B                  <1> 	pop	ebx ; ***
  3441 00005C46 5E                  <1> 	pop	esi ; ****
  3442 00005C47 C3                  <1> 	retn
  3443                              <1> rwdsk_lba_reset:
  3444                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3445                              <1> 	;int	13h
  3446                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3447                              <1> 	;mov	ah, 5 ; Alternate reset	 
  3448                              <1> 	;call	int13h
  3449                              <1> 	;jnc	short rwdsk_lba_retry
  3450                              <1> 	; 12/07/2022
  3451 00005C48 30C0                <1> 	xor	al, al ; 0 ; reset
  3452 00005C4A E81BC4FFFF          <1> 	call	DISK_IO
  3453 00005C4F 73DB                <1> 	jnc	short rwdsk_lba_retry
  3454                              <1> 
  3455 00005C51 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3456 00005C53 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3457                              <1> 
  3458                              <1> 	; 12/07/2022 
  3459                              <1> 	;	(CHS Read/Write setup is not needed here.)
  3460                              <1> 	; 	(LBA address will be converted to CHS parameters 
  3461                              <1> 	;	in 'DISK_IO' procedure when/if it is required.)
  3462                              <1>  
  3463                              <1> ;	; CHS read (convert LBA address to CHS values)	
  3464                              <1> ;rwdsk_chs:
  3465                              <1> ;	; 10/07/2015
  3466                              <1> ;	sub	esi, drv.status
  3467                              <1> ;	mov	ecx, esi
  3468                              <1> ;	add 	esi, drv.error
  3469                              <1> ;	; 02/07/2015
  3470                              <1> ;	; 16/06/2015
  3471                              <1> ;	; 11/06/2015 
  3472                              <1> ;	push	ebx ; ** ; buffer
  3473                              <1> ;	shl	ecx, 1
  3474                              <1> ;	push	ecx ; * 
  3475                              <1> ;	;
  3476                              <1> ;	mov	ebx, ecx
  3477                              <1> ;	mov	[rwdsk], dh ; 02/07/2015
  3478                              <1> ;	xor	edx, edx ; 0
  3479                              <1> ;	; 09/01/2022
  3480                              <1> ;	;sub	ecx, ecx 
  3481                              <1> ;       add     ebx, drv.spt
  3482                              <1> ;	mov	cx, [ebx] ; sector per track
  3483                              <1> ;		; EDX:EAX = LBA
  3484                              <1> ;	div	ecx
  3485                              <1> ;	mov	cl, dl	; sector number - 1
  3486                              <1> ;	inc	cl	; sector number (1 based)
  3487                              <1> ;	pop	ebx ; * ; 11/06/2015
  3488                              <1> ;	;push	cx
  3489                              <1> ;	; 09/01/2022
  3490                              <1> ;	push	ecx
  3491                              <1> ;	add     ebx, drv.heads
  3492                              <1> ;	mov	cx, [ebx] ; heads
  3493                              <1> ;	xor	edx, edx
  3494                              <1> ;		; EAX = cylinders * heads + head
  3495                              <1> ;	div	ecx
  3496                              <1> ;	;pop	cx     ; sector number
  3497                              <1> ;	; 09/01/2022
  3498                              <1> ;	pop	ecx
  3499                              <1> ;	mov	dh, dl ; head number
  3500                              <1> ;	mov	dl, [drv]
  3501                              <1> ;	mov	ch, al ; cylinder (bits 0-7)
  3502                              <1> ;	shl	ah, 6
  3503                              <1> ;	or	cl, ah ; cylinder (bits 8-9)
  3504                              <1> ;		       ; sector (bits 0-7)
  3505                              <1> ;	pop	ebx ; ** ; buffer ; 11/06/2015
  3506                              <1> ;		; CL = sector (bits 0-5)
  3507                              <1> ;		;      cylinder (bits 8-9 -> bits 6-7)
  3508                              <1> ;		; CH = cylinder (bits 0-7)
  3509                              <1> ;		; DH = head
  3510                              <1> ;		; DL = drive
  3511                              <1> ;	;
  3512                              <1> ;	mov	byte [retry_count], 4
  3513                              <1> ;rwdsk_retry:	
  3514                              <1> ;	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3515                              <1> ;	; 08/07/2022
  3516                              <1> ;	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3517                              <1> ;	mov	al, 1 ; sector count	
  3518                              <1> ;	;int	13h
  3519                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3520                              <1> ;	call	int13h
  3521                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3522                              <1> ;	jnc	short rwdsk_ok ; ah = 0
  3523                              <1> ;	cmp	ah, 80h ; time out ?
  3524                              <1> ;	je	short rwdsk_fails
  3525                              <1> ;	dec	byte [retry_count]
  3526                              <1> ;	jnz	short rwdsk_reset
  3527                              <1> ;rwdsk_fails:
  3528                              <1> ;	stc
  3529                              <1> ;rwdsk_ok:
  3530                              <1> ;	pop	ebx ; ***
  3531                              <1> ;	pop	esi ; ****
  3532                              <1> ;	retn
  3533                              <1> ;rwdsk_reset:
  3534                              <1> ;	; 02/02/2015
  3535                              <1> ;	sub	ah, ah
  3536                              <1> ;	cmp	dl, 80h
  3537                              <1> ;	jb	short rwdsk_fd_reset
  3538                              <1> ;	;mov	ah, 0Dh ; Alternate reset
  3539                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3540                              <1> ;	mov	ah, 5  ; Alternate reset
  3541                              <1> ;rwdsk_fd_reset:
  3542                              <1> ;	;int	13h
  3543                              <1> ;	call	int13h
  3544                              <1> ;	jnc	short rwdsk_retry
  3545                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3546                              <1> ;	jmp 	short rwdsk_ok
  3547                              <1> 
  3548                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3549                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3550                              <1> ;
  3551                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3552                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3553                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3554                              <1> ; that uses hardware -transfer has been completed- interrupt inside it. 
  3555                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3556                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3557                              <1> ; as in original unix v1.
  3558                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3559                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3560                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3561                              <1> ;
  3562                              <1> ; Erdogan tan (10/07/2015) 
  3563                              <1> 
  3564                              <1> ;drum: / interrupt handler
  3565                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3566                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3567                              <1> ;                                      / error
  3568                              <1> ;               br 3f / no, error
  3569                              <1> ;       br      2f / error
  3570                              <1> ;
  3571                              <1> ;disk:
  3572                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3573                              <1> ;       jmp     *$0f
  3574                              <1> ;0:
  3575                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3576                              <1> ;      	        br 3f / no, errors
  3577                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3578                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3579                              <1> ;                        / to 1f
  3580                              <1> ;       br      4f
  3581                              <1> ;1:
  3582                              <1> ;       bit     $20000,rkcs
  3583                              <1> ;       beq     4f / wait for seek complete
  3584                              <1> ;       mov     $0b,0b-2
  3585                              <1> ;       mov     rkap,r1
  3586                              <1> ;2:
  3587                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3588                              <1> ;                          / the disk buffer
  3589                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3590                              <1> ;       inc     r1
  3591                              <1> ;       asr     (r1)
  3592                              <1> ;       asr     (r1)
  3593                              <1> ;       asr     (r1) / reissue request
  3594                              <1> ;       dec     r1
  3595                              <1> ;3:
  3596                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3597                              <1> ;       mov     ac,-(sp)
  3598                              <1> ;       mov     mq,-(sp) / put these on the stack
  3599                              <1> ;       mov     sc,-(sp)
  3600                              <1> ;       jsr     r0,poke
  3601                              <1> ;       mov     (sp)+,sc
  3602                              <1> ;       mov     (sp)+,mq / pop them off stack
  3603                              <1> ;       mov     (sp)+,ac
  3604                              <1> ;4:
  3605                              <1> ;       jmp     retisp / u4-3
  3606                              <1> ;
  3607                              <1> ;trapt:                  / r2 points to the
  3608                              <1> ;       mov     (r0)+,r2 / device control register
  3609                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3610                              <1> ;       tst     (sp)+
  3611                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3612                              <1> ;       bge     4b / device still active so branch
  3613                              <1> ;       bit     (r0),active / was device busy?
  3614                              <1> ;       beq     4b / no, stray interrupt
  3615                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3616                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3617                              <1> ;       bge     2f / if no error jump to 2f
  3618                              <1> ;       tst     (r0)+ / skip on error
  3619                              <1> ; 2:
  3620                              <1> ;       jmp     (r0)
  3621                              <1> 
  3622                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatibility code
  3623                              <1> get_system_time:
  3624                              <1> 	; 27/10/2021
  3625                              <1> 	; 21/02/2020 - Retro UNIX 386 v2
  3626                              <1> 	; get system time
  3627                              <1> 	;  (from recent value which is saved in RTC interrupt)
  3628                              <1> 	; Input:
  3629                              <1> 	; 	none
  3630                              <1> 	; Return:
  3631                              <1> 	;   	eax = system time in unix epoch format 
  3632                              <1> 	;
  3633                              <1> 	; Modified registers: eax, ecx, edx
  3634                              <1> 	
  3635                              <1> 	; 27/11/2021
  3636 00005C55 53                  <1> 	push	ebx
  3637 00005C56 E8E8D0FFFF          <1> 	call	epoch
  3638 00005C5B 5B                  <1> 	pop	ebx
  3639 00005C5C C3                  <1> 	retn
  3640                              <1> 	
  3641                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  3642                              <1> 	;  ('get_serial_number' is not used in v1.2 kernel)
  3643                              <1> ;get_serial_number:
  3644                              <1> 	; temporary - 21/02/2020
  3645                              <1> 	; 26/04/2020 (esi)
  3646                              <1> 	; 25/04/2020
  3647                              <1> 	; (Possible) Modified registers: eax, ecx, edx
  3648                              <1> 	; (edi, ebx & esi registers must be preserved)
  3649                              <1> 	; Return:
  3650                              <1> 	; eax = 32 bit serial number  
  3651                              <1> 	; (edx = high 32 bit of 64 bit serial number)
  3652                              <1> 	; -64 bit serial numbers will not be used in RUNIX 386 v2-
  3653                              <1> 	
  3654                              <1> 	;retn
  2095                                  %include 'u9.s'      ; 29/06/2015
  2096                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2097                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2098                              <1> ; ****************************************************************************
  2099                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - SYS9.INC
  2100                              <1> ; Last Modification: 12/06/2022
  2101                              <1> ; ----------------------------------------------------------------------------
  2102                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2103                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2104                              <1> ;
  2105                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2106                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2107                              <1> ; <Bell Laboratories (17/3/1972)>
  2108                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2109                              <1> ;
  2110                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2111                              <1> ;
  2112                              <1> ; ****************************************************************************
  2113                              <1> 
  2114                              <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - Printer BIOS (Functions)
  2115                              <1> 
  2116                              <1> getch:
  2117                              <1> 	; 30/06/2015
  2118                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2119 00005C5D 28C0                <1> 	sub	al, al ; 0
  2120                              <1> getch_q: ; 06/08/2015
  2121 00005C5F 8A25[56680000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2122 00005C65 EB06                <1>         jmp     short getc_n
  2123                              <1> 
  2124                              <1> getc: 
  2125                              <1> 	; 12/11/2015
  2126                              <1> 	; 15/09/2015
  2127                              <1> 	; 01/07/2015
  2128                              <1> 	; 30/06/2015
  2129                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2130                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2131                              <1> 	;
  2132                              <1> 	; Retro UNIX 8086 v1 modification !
  2133                              <1> 	; 
  2134                              <1> 	; 'getc' gets (next) character 
  2135                              <1> 	;	 from requested TTY (keyboard) buffer 
  2136                              <1> 	; INPUTS ->
  2137                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2138                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2139                              <1> 	;	(Keyboard buffer will point to 
  2140                              <1> 	;			next character at next call)
  2141                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2142                              <1> 	;	(Keyboard buffer will point to 
  2143                              <1> 	;			current character at next call)
  2144                              <1> 	; OUTPUTS ->
  2145                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2146                              <1> 	;     			 ZF=0 -> AX has (current) character
  2147                              <1> 	;      AL = ascii code
  2148                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2149                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2150                              <1> 	; Original UNIX V1 'getc': 
  2151                              <1> 	;		get a character off character list
  2152                              <1> 	;
  2153                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2154                              <1> 	;
  2155                              <1> 	; 30/06/2015 (32 bit modifications)
  2156                              <1> 	; 16/07/2013
  2157                              <1> 	; mov 	[getctty], ah
  2158                              <1> 	;
  2159                              <1> 
  2160 00005C67 8A25[996D0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2161                              <1> getc_n:
  2162                              <1> 	; 30/06/2015
  2163 00005C6D 08E4                <1> 	or	ah, ah
  2164 00005C6F 740D                <1> 	jz	short getc0 
  2165 00005C71 D0E4                <1> 	shl	ah, 1
  2166 00005C73 0FB6DC              <1> 	movzx	ebx, ah
  2167 00005C76 81C3[58680000]      <1> 	add	ebx, ttychr
  2168 00005C7C EB05                <1> 	jmp	short getc1
  2169                              <1> getc0:
  2170 00005C7E BB[58680000]        <1> 	mov	ebx, ttychr
  2171                              <1> getc1:
  2172 00005C83 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2173                              <1> 				; (by kb_int)	
  2174 00005C86 6609C9              <1> 	or	cx, cx
  2175 00005C89 7507                <1> 	jnz	short getc2
  2176 00005C8B 20C0                <1> 	and 	al, al
  2177 00005C8D 7415                <1> 	jz	short getc_s
  2178                              <1> 	;xor	ax, ax
  2179                              <1> 	; 30/11/2021
  2180 00005C8F 31C0                <1> 	xor	eax, eax
  2181 00005C91 C3                  <1> 	retn
  2182                              <1> getc2:	
  2183 00005C92 20C0                <1> 	and	al, al
  2184 00005C94 6689C8              <1> 	mov	ax, cx
  2185 00005C97 66B90000            <1> 	mov	cx, 0
  2186 00005C9B 7506                <1> 	jnz	short getc3
  2187                              <1> getc_sn:
  2188 00005C9D 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2189 00005CA0 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2190                              <1> getc3:
  2191 00005CA3 C3                  <1> 	retn
  2192                              <1> getc_s:
  2193                              <1> 	; 12/11/2015
  2194                              <1> 	; 15/09/2015
  2195                              <1> 	; 01/07/2015
  2196                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2197                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2198                              <1> 	;
  2199                              <1> 	; tty  of the current process is not 
  2200                              <1> 	; current tty (ptty); so, current process only 
  2201                              <1> 	; can use keyboard input when its tty becomes 
  2202                              <1> 	; current tty (ptty).
  2203                              <1> 	; 'sleep' is for preventing an endless lock
  2204                              <1> 	; during this tty input request.
  2205                              <1> 	; (Because, the user is not looking at the video page
  2206                              <1> 	; of the process to undersand there is a keyboard
  2207                              <1> 	; input request.)
  2208                              <1> 	;
  2209                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2210                              <1> 	;
  2211                              <1> 	; 05/10/2013
  2212                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2213                              <1> 	;
  2214                              <1> 	; 10/10/2013
  2215                              <1> gcw0:
  2216 00005CA4 B10A                <1> 	mov	cl, 10 ; ch = 0
  2217                              <1> gcw1:	
  2218                              <1> 	; 12/11/2015
  2219 00005CA6 E8CFD6FFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2220                              <1> 	; 10/10/2013
  2221 00005CAB E850EBFFFF          <1> 	call	idle
  2222 00005CB0 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2223                              <1> 				; (by kb_int)
  2224 00005CB3 6609C0              <1> 	or	ax, ax
  2225                              <1> ;	jnz	short gcw3
  2226 00005CB6 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2227                              <1> 	; 30/06/2015
  2228 00005CB8 FEC9                <1> 	dec	cl
  2229 00005CBA 75EA                <1> 	jnz	short gcw1
  2230                              <1> 	;
  2231 00005CBC 8A25[996D0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2232                              <1> ;	; 10/12/2013
  2233                              <1> ;	cmp 	ah, [ptty]
  2234                              <1> ;	jne	short gcw2
  2235                              <1> ;	; 14/02/2014
  2236                              <1> ;	cmp	byte [u.uno], 1
  2237                              <1> ;	jna	short gcw0		
  2238                              <1> ;gcw2:
  2239 00005CC2 E8C6EBFFFF          <1> 	call	sleep
  2240                              <1> 	;
  2241                              <1> 	; 20/09/2013
  2242 00005CC7 8A25[996D0000]      <1> 	mov	ah, [u.ttyn]
  2243 00005CCD 30C0                <1> 	xor 	al, al
  2244 00005CCF EB9C                <1> 	jmp	short getc_n
  2245                              <1> ;gcw3:
  2246                              <1> gcw2: 	; 15/09/2015
  2247                              <1> 	; 10/10/2013
  2248 00005CD1 30C9                <1> 	xor	cl, cl
  2249 00005CD3 EBC8                <1> 	jmp	short getc_sn
  2250                              <1> 
  2251                              <1> putc:	
  2252                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2253                              <1> 	; 13/08/2015
  2254                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2255                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2256                              <1> 	;
  2257                              <1> 	; Retro UNIX 8086 v1 modification !
  2258                              <1> 	; 
  2259                              <1> 	; 'putc' puts a character 
  2260                              <1> 	;	 onto requested (tty) video page or
  2261                              <1> 	;	 serial port
  2262                              <1> 	; INPUTS ->
  2263                              <1> 	;     AL = ascii code of the character
  2264                              <1> 	;     AH = video page (tty) number (0 to 7)
  2265                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2266                              <1> 	; OUTPUTS ->
  2267                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2268                              <1> 	;      			ZF=0 -> AX has (current) character
  2269                              <1> 	;     cf=0 and AH = 0 -> no error
  2270                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)
  2271                              <1> 	; 
  2272                              <1> 	; Original UNIX V1 'putc': 
  2273                              <1> 	;     put a character at the end of character list
  2274                              <1> 	;
  2275                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2276                              <1> 	;
  2277 00005CD5 80FC07              <1> 	cmp	ah, 7
  2278 00005CD8 770A                <1>         ja      short sndc ; 05/12/2021
  2279                              <1> 	; 30/06/2015
  2280 00005CDA 0FB6DC              <1> 	movzx	ebx, ah
  2281                              <1> 	; 13/08/2015
  2282 00005CDD B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2283 00005CDF E9BDB6FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2284                              <1> 
  2285                              <1> sndc:   ; <Send character>
  2286                              <1> 	;
  2287                              <1> 	; 12/01/2022
  2288                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2289                              <1> 	; 17/11/2015
  2290                              <1> 	; 16/11/2015
  2291                              <1> 	; 11/11/2015
  2292                              <1> 	; 10/11/2015
  2293                              <1> 	; 09/11/2015
  2294                              <1> 	; 08/11/2015
  2295                              <1> 	; 07/11/2015
  2296                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2297                              <1> 	; 29/10/2015
  2298                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2299                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2300                              <1> 	;
  2301                              <1> 	; Retro UNIX 8086 v1 feature only !
  2302                              <1> 	;
  2303                              <1> 	; ah = [u.ttyn]
  2304                              <1> 	;
  2305                              <1> 	; 30/06/2015
  2306 00005CE4 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2307                              <1> 	; 07/11/2015
  2308 00005CE7 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2309                              <1> sndc0:
  2310                              <1> 	; 07/11/2015
  2311 00005CEA E8ECEBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2312 00005CEF 7405                <1> 	jz	short sndc1
  2313 00005CF1 E884D6FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2314                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2315                              <1> sndc1:
  2316                              <1> 	; 16/11/2015
  2317                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2318                              <1> 	; 24/12/2021
  2319 00005CF6 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2320                              <1> sndcx:
  2321 00005CF8 8A83[9A680000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2322 00005CFE 8AA3[98680000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2323                              <1> 	;
  2324                              <1> 	; 17/11/2015
  2325                              <1> 	; check 'request for response' status
  2326 00005D04 80BB[94680000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2327 00005D0B 740A                <1> 	jz	short query
  2328                              <1> response:
  2329 00005D0D FE05[97680000]      <1> 	inc 	byte [comqr] ; query or response status
  2330 00005D13 B0FF                <1> 	mov	al, 0FFh	 
  2331 00005D15 EB14                <1> 	jmp	short sndc3
  2332                              <1> query:
  2333 00005D17 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2334 00005D19 750E                <1> 	jnz 	short sndc2 ; normal character
  2335                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2336                              <1> 	;je	short sndc2  ; yes, already responded
  2337                              <1> 	; 16/11/2015
  2338                              <1> 	; query: request for response (again)
  2339 00005D1B 8883[98680000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2340 00005D21 FE05[97680000]      <1> 	inc 	byte [comqr] ; query or response status
  2341 00005D27 EB02                <1> 	jmp	short sndc3
  2342                              <1> sndc2:
  2343 00005D29 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2344                              <1> sndc3:
  2345 00005D2B 8883[9A680000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2346 00005D31 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2347                              <1> 	; 30/06/2015
  2348 00005D33 E870CFFFFF          <1> 	call	sp_status ; get serial port status
  2349                              <1> 	; AL = Line status, AH = Modem status
  2350                              <1> 	; 07/11/2015
  2351 00005D38 A880                <1> 	test	al, 80h
  2352 00005D3A 7504                <1> 	jnz	short sndc4
  2353 00005D3C A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2354 00005D3E 751A                <1> 	jnz	short sndc5
  2355                              <1> sndc4: 	; Check line status again
  2356                              <1> 	; 16/11/2015
  2357                              <1> 	;push	cx
  2358                              <1> 	; 24/12/2021
  2359 00005D40 51                  <1> 	push	ecx
  2360                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2361                              <1> 	; 12/01/2022
  2362 00005D41 31C9                <1> 	xor	ecx, ecx
  2363 00005D43 B106                <1> 	mov	cl, 6
  2364 00005D45 E84EB7FFFF          <1> 	call	WAITF
  2365                              <1> 	;pop	cx
  2366                              <1> 	; 24/12/1021
  2367 00005D4A 59                  <1> 	pop	ecx
  2368                              <1> 	;
  2369 00005D4B 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2370 00005D4D E856CFFFFF          <1> 	call	sp_status ; get serial port status
  2371                              <1> 	; 16/11/2015
  2372                              <1> 	; 09/11/2015
  2373                              <1> 	; 08/11/2015
  2374 00005D52 A880                <1> 	test	al, 80h	; time out error
  2375 00005D54 7565                <1>         jnz     short sndc7
  2376 00005D56 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2377 00005D58 7461                <1>         jz	short sndc7
  2378                              <1> sndc5:  
  2379 00005D5A 8A83[9A680000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2380 00005D60 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2381 00005D64 28DE                <1> 	sub	dh, bl
  2382 00005D66 EE                  <1> 	out	dx, al	   ; send on serial port
  2383                              <1> 	; 10/11/2015
  2384                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2385                              <1> 	; (to improve text flow to the terminal)
  2386                              <1> 	; ('diskette.inc': 'WAITF')
  2387                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2388                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2389                              <1> 	;push	cx
  2390                              <1> 	; 24/12/2021
  2391 00005D67 51                  <1> 	push	ecx
  2392                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2393                              <1> 	; 12/01/2022
  2394 00005D68 29C9                <1> 	sub	ecx, ecx
  2395 00005D6A B106                <1> 	mov	cl, 6
  2396 00005D6C E827B7FFFF          <1> 	call	WAITF
  2397                              <1> 	;pop	cx
  2398                              <1> 	; 24/12/1021
  2399 00005D71 59                  <1> 	pop	ecx
  2400                              <1>     	;
  2401                              <1> 	; 07/11/2015
  2402 00005D72 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2403                              <1> 	;
  2404 00005D74 E82FCFFFFF          <1> 	call	sp_status ; get serial port status
  2405                              <1> 	; AL = Line status, AH = Modem status
  2406                              <1> 	;
  2407 00005D79 E85DEBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2408 00005D7E 7405                <1> 	jz	short sndc6
  2409 00005D80 E8F5D5FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2410                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2411                              <1> sndc6:
  2412 00005D85 3C80                <1> 	cmp	al, 80h
  2413 00005D87 7332                <1> 	jnb	short sndc7		
  2414                              <1> 	;
  2415 00005D89 803D[97680000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2416 00005D90 7244                <1> 	jb	short sndc8 	; no, normal character
  2417 00005D92 883D[97680000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2418                              <1> 	; 17/11/2015
  2419 00005D98 E863EAFFFF          <1> 	call	idle
  2420                              <1> 	;
  2421 00005D9D 38BB[9A680000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2422                              <1>         ;ja	sndc2       ; response (will be followed by
  2423                              <1> 			    ; a normal character)
  2424                              <1> 	; 24/12/2021
  2425 00005DA3 7602                <1> 	jna	short sndc_10
  2426 00005DA5 EB82                <1> 	jmp	sndc2
  2427                              <1> sndc_10:
  2428                              <1> 	; Query request must be responded by the terminal
  2429                              <1> 	; before sending a normal character !
  2430 00005DA7 53                  <1> 	push	ebx
  2431                              <1> 	;push	cx ; *** cl = character (to be sent)
  2432                              <1> 	; 24/12/2021
  2433 00005DA8 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2434 00005DA9 8A25[996D0000]      <1> 	mov	ah, [u.ttyn]
  2435 00005DAF E8D9EAFFFF          <1> 	call	sleep ; this process will be awakened by
  2436                              <1> 		      ; received data available interrupt
  2437                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2438                              <1> 	; 24/12/2021
  2439 00005DB4 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2440 00005DB5 5B                  <1> 	pop	ebx
  2441 00005DB6 E93DFFFFFF          <1>         jmp	sndcx
  2442                              <1> sndc7:
  2443                              <1> 	 ; 16/11/2015
  2444 00005DBB 803D[97680000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2445 00005DC2 7213                <1> 	jb	short sndc9 	; no
  2446                              <1> 	;
  2447 00005DC4 88BB[98680000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2448 00005DCA 88BB[9A680000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2449                              <1> 	;
  2450 00005DD0 883D[97680000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2451                              <1> sndc8:
  2452 00005DD6 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2453                              <1> sndc9:
  2454                              <1> 	; AL = Line status, AH = Modem status
  2455 00005DD7 C3                  <1> 	retn
  2456                              <1> 
  2457                              <1> get_cpos:
  2458                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2459                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2460                              <1> 	;
  2461                              <1> 	; INPUT -> bl = video page number
  2462                              <1> 	; RETURN -> dx = cursor position
  2463                              <1> 
  2464 00005DD8 53                  <1> 	push	ebx
  2465 00005DD9 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2466 00005DDC D0E3                <1> 	shl	bl, 1
  2467 00005DDE 81C3[46680000]      <1> 	add	ebx, cursor_posn
  2468 00005DE4 668B13              <1> 	mov	dx, [ebx]
  2469 00005DE7 5B                  <1> 	pop	ebx
  2470 00005DE8 C3                  <1> 	retn
  2471                              <1> 
  2472                              <1> read_ac_current:
  2473                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2474                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2475                              <1> 	;
  2476                              <1> 	; INPUT -> bl = video page number
  2477                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2478                              <1> 
  2479 00005DE9 E819B7FFFF          <1> 	call 	find_position ; 'video.inc'
  2480                              <1> 	; dx = status port
  2481                              <1> 	; esi = cursor location/address
  2482 00005DEE 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2483 00005DF4 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2484 00005DF7 C3                  <1> 	retn
  2485                              <1> 
  2486                              <1> syssleep:
  2487                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2488                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2489                              <1> 	;
  2490                              <1> 	; Retro UNIX 8086 v1 feature only
  2491                              <1> 	; (INPUT -> none)
  2492                              <1> 	;
  2493 00005DF8 0FB61D[B56D0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2494 00005DFF 8AA3[63690000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2495 00005E05 E883EAFFFF          <1> 	call	sleep
  2496 00005E0A E97ED4FFFF          <1> 	jmp	sysret
  2497                              <1> 
  2498                              <1> vp_clr:
  2499                              <1> 	; Reset/Clear Video Page
  2500                              <1> 	;
  2501                              <1> 	; 05/12/2021 - (Retro UNIX 386 v1.2)
  2502                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2503                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2504                              <1> 	;
  2505                              <1> 	; Retro UNIX 8086 v1 feature only !
  2506                              <1> 	;
  2507                              <1> 	; INPUTS -> 
  2508                              <1> 	;   BL = video page number	 
  2509                              <1> 	;
  2510                              <1> 	; OUTPUT ->
  2511                              <1> 	;   none
  2512                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2513                              <1> 	;
  2514                              <1> 	; 04/12/2013
  2515 00005E0F 28C0                <1> 	sub	al, al
  2516                              <1> 	; al = 0 (clear video page)
  2517                              <1> 	; bl = video page
  2518 00005E11 B407                <1> 	mov	ah, 07h
  2519                              <1> 	; ah = 7 (attribute/color)
  2520                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2521                              <1> 	; 05/12/2021
  2522 00005E13 31C9                <1> 	xor	ecx, ecx
  2523 00005E15 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2524 00005E19 E813B7FFFF          <1> 	call	scroll_up
  2525                              <1> 	; bl = video page
  2526                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2527                              <1> 	; 05/12/2021
  2528 00005E1E 31D2                <1> 	xor	edx, edx
  2529 00005E20 E986B6FFFF          <1> 	jmp 	set_cpos
  2530                              <1> 
  2531                              <1> sysmsg:
  2532                              <1> 	; 11/12/2021
  2533                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2534                              <1> 	; 11/11/2015
  2535                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2536                              <1> 	; Print user-application message on user's console tty
  2537                              <1> 	;
  2538                              <1> 	; Input -> EBX = Message address
  2539                              <1> 	;	   ECX = Message length (max. 255)
  2540                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2541                              <1> 	;
  2542 00005E25 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2543                              <1> 	;ja	sysret ; nothing to do with big message size
  2544 00005E2B 7779                <1> 	ja	short sysmsg8 ; 11/12/2021
  2545 00005E2D 08C9                <1> 	or	cl, cl
  2546                              <1> 	;jz	sysret
  2547 00005E2F 7475                <1> 	jz	short sysmsg8 ; 11/12/2021
  2548 00005E31 20D2                <1> 	and	dl, dl
  2549 00005E33 7502                <1> 	jnz	short sysmsg0
  2550 00005E35 B207                <1> 	mov	dl, 07h ; default color
  2551                              <1> 		; (black background, light gray character)
  2552                              <1> sysmsg0:
  2553 00005E37 891D[886D0000]      <1> 	mov	[u.base], ebx
  2554 00005E3D 8815[57680000]      <1> 	mov	[ccolor], dl ; color attributes
  2555 00005E43 89E5                <1> 	mov	ebp, esp
  2556 00005E45 31DB                <1> 	xor	ebx, ebx ; 0
  2557 00005E47 891D[906D0000]      <1> 	mov	[u.nread], ebx ; 0
  2558                              <1> 	;
  2559 00005E4D 381D[D66D0000]      <1> 	cmp	[u.kcall], bl ; 0
  2560 00005E53 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2561                              <1> 	;
  2562 00005E55 890D[8C6D0000]      <1> 	mov	[u.count], ecx
  2563 00005E5B 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ ; 04/12/2021
  2564                              <1> 	; 04/12/2021
  2565                              <1> 	; (dword alignment for esp)
  2566 00005E5C F6C103              <1> 	test	cl, 3
  2567 00005E5F 7404                <1> 	jz	short sysmsg_7
  2568 00005E61 80C903              <1> 	or	cl, 3
  2569 00005E64 41                  <1> 	inc	ecx
  2570                              <1> sysmsg_7:
  2571 00005E65 29CC                <1> 	sub	esp, ecx
  2572 00005E67 89E7                <1> 	mov	edi, esp
  2573 00005E69 89E6                <1> 	mov	esi, esp
  2574 00005E6B 66891D[D06D0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2575                              <1> 	; 11/11/2015 
  2576 00005E72 8A25[9A6D0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2577                              <1> 	; 0 = none
  2578 00005E78 FECC                <1> 	dec	ah
  2579 00005E7A 790C                <1> 	jns	short sysmsg1 
  2580 00005E7C 8A1D[B56D0000]      <1> 	mov	bl, [u.uno] ; process number	
  2581 00005E82 8AA3[63690000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2582                              <1> sysmsg1:
  2583 00005E88 8825[996D0000]      <1> 	mov	[u.ttyn], ah
  2584                              <1> sysmsg2:
  2585 00005E8E E89EF5FFFF          <1> 	call	cpass
  2586 00005E93 7416                <1> 	jz	short sysmsg5
  2587 00005E95 AA                  <1> 	stosb
  2588 00005E96 20C0                <1> 	and	al, al
  2589 00005E98 75F4                <1> 	jnz	short sysmsg2
  2590                              <1> sysmsg3:
  2591 00005E9A 80FC07              <1> 	cmp	ah, 7 ; tty number
  2592 00005E9D 7711                <1> 	ja	short sysmsg6 ; serial port
  2593 00005E9F E83E000000          <1> 	call	print_cmsg
  2594                              <1> sysmsg4:
  2595 00005EA4 89EC                <1> 	mov	esp, ebp
  2596                              <1> sysmsg8: ; 11/12/2021	
  2597 00005EA6 E9E2D3FFFF          <1> 	jmp	sysret
  2598                              <1> sysmsg5:
  2599 00005EAB C60700              <1> 	mov	byte [edi], 0
  2600 00005EAE EBEA                <1> 	jmp	short sysmsg3
  2601                              <1> sysmsg6:
  2602 00005EB0 8A06                <1> 	mov	al, [esi]
  2603 00005EB2 E82DFEFFFF          <1> 	call	sndc
  2604 00005EB7 72EB                <1> 	jc	short sysmsg4
  2605 00005EB9 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2606 00005EBC 76E6                <1> 	jna	short sysmsg4
  2607 00005EBE 46                  <1> 	inc 	esi
  2608 00005EBF 8A25[996D0000]      <1> 	mov	ah, [u.ttyn]
  2609 00005EC5 EBE9                <1> 	jmp	short sysmsg6
  2610                              <1> 
  2611                              <1> sysmsgk: ; Temporary (01/07/2015)
  2612                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2613                              <1> 	; (ECX -character count- will not be considered)
  2614 00005EC7 8B35[886D0000]      <1> 	mov	esi, [u.base]
  2615 00005ECD 8A25[56680000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2616 00005ED3 8825[996D0000]      <1> 	mov	[u.ttyn], ah
  2617 00005ED9 C605[D66D0000]00    <1> 	mov	byte [u.kcall], 0
  2618 00005EE0 EBB8                <1> 	jmp	short sysmsg3
  2619                              <1> 	
  2620                              <1> print_cmsg: 
  2621                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2622                              <1> 	;
  2623                              <1> 	; print message (on user's console tty) 
  2624                              <1> 	;	with requested color
  2625                              <1> 	;
  2626                              <1> 	; INPUTS:
  2627                              <1> 	;	esi = message address
  2628                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2629                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2630                              <1> 	;
  2631 00005EE2 AC                  <1> 	lodsb
  2632                              <1> pcmsg1:
  2633 00005EE3 56                  <1> 	push 	esi
  2634 00005EE4 0FB61D[996D0000]    <1>         movzx   ebx, byte [u.ttyn]
  2635 00005EEB 8A25[57680000]      <1> 	mov	ah, [ccolor]
  2636 00005EF1 E8ABB4FFFF          <1> 	call 	write_tty
  2637 00005EF6 5E                  <1> 	pop	esi
  2638 00005EF7 AC                  <1> 	lodsb
  2639 00005EF8 20C0                <1> 	and 	al, al  ; 0
  2640 00005EFA 75E7                <1> 	jnz 	short pcmsg1
  2641 00005EFC C3                  <1> 	retn
  2642                              <1> 
  2643                              <1> sysgeterr:
  2644                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.2
  2645                              <1> 	; 09/12/2015
  2646                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2647                              <1> 	; Get last error number or page fault count
  2648                              <1> 	; (for debugging)
  2649                              <1> 	;
  2650                              <1> 	; Input -> EBX = return type
  2651                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2652                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2653                              <1> 	;	   FFFFFFFEh = total page fault count
  2654                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2655                              <1> 	;
  2656                              <1> 	; Output -> EAX = last error number or page fault count
  2657                              <1> 	;	   (depending on EBX input)
  2658                              <1> 	; 	
  2659 00005EFD 21DB                <1> 	and 	ebx, ebx
  2660 00005EFF 750F                <1> 	jnz	short glerr_2
  2661                              <1> glerr_0:
  2662 00005F01 A1[D86D0000]        <1> 	mov	eax, [u.error]
  2663                              <1> glerr_1:
  2664 00005F06 A3[646D0000]        <1> 	mov	[u.r0], eax
  2665                              <1> 	;retn
  2666                              <1>  	; 16/02/2022 (BugFix)
  2667 00005F0B E97DD3FFFF          <1> 	jmp	sysret
  2668                              <1> glerr_2:
  2669 00005F10 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2670 00005F11 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2671 00005F13 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2672 00005F14 75EB                <1> 	jnz	short glerr_0
  2673 00005F16 A1[DC680000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2674 00005F1B EBE9                <1>         jmp     short glerr_1
  2675                              <1> glerr_3:
  2676 00005F1D A1[DC6D0000]        <1> 	mov 	eax, [u.pfcount]
  2677 00005F22 EBE2                <1> 	jmp	short glerr_1
  2678                              <1> 
  2679                              <1> ; 12/06/2022 - Retro UNIX 386 v1.2 - PRINTER BIOS (Functions)		
  2680                              <1> 
  2681                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2682                              <1> ;
  2683                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2684                              <1> ; PRINTER_IO								       :
  2685                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2686                              <1> ; INPUT 								       :
  2687                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2688                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2689                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2690                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2691                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2692                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2693                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2694                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2695                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2696                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2697                              <1> ;		   |	   |	   |	   |	   |			       :
  2698                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2699                              <1> ;		   |	   |	   |	   |				       :
  2700                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2701                              <1> ;		   |	   |	   |					       :
  2702                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2703                              <1> ;		   |	   |						       :
  2704                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2705                              <1> ;		   |							       :
  2706                              <1> ;		   |_ 1 = NOT BUSY					       :
  2707                              <1> ;									       :
  2708                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2709                              <1> ;		IN @PRINTER_BASE AREA					       :
  2710                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2711                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2712                              <1> ;									       :
  2713                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2714                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2715                              <1> ;									       :
  2716                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2717                              <1> ;		ALL OTHERS UNCHANGED					       :
  2718                              <1> ;-------------------------------------------------------------------------------
  2719                              <1> 
  2720                              <1> int17h:
  2721                              <1> 	; 12/06/2022 - Retro UNIX 386 v1.2
  2722                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2723                              <1> 	;
  2724                              <1> 	; (Default printer port: 378h) ; LPT1
  2725                              <1> 	; (Number of printers = 1)
  2726                              <1> 	
  2727                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2728                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2729                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2730                              <1> 
  2731                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2732                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2733                              <1> 
  2734                              <1> 	; INPUT:
  2735                              <1> 	;	ah = 0 -> print the character in AL 
  2736                              <1> 	;		 (sys write with write count >0)
  2737                              <1> 	;	ah = 1 -> initialize printer port
  2738                              <1> 	;		 (sys open)	
  2739                              <1> 	;	ah = 2 -> read the printer status 
  2740                              <1> 	;		 (sys write with write count = 0)
  2741                              <1> 	; OUTPUT:
  2742                              <1> 	;	ah = printer status
  2743                              <1> 
  2744                              <1> 	; Modified registers: eax, ecx, edx
  2745                              <1> 
  2746                              <1> PRINTER_IO_1:
  2747 00005F24 08E4                <1> 	or	ah, ah
  2748 00005F26 7417                <1> 	jz	short _b20
  2749 00005F28 FECC                <1> 	dec	ah
  2750 00005F2A 7444                <1> 	jz	short _b80
  2751                              <1> 	;dec 	ah
  2752                              <1> 	;jz	short _b50
  2753                              <1> _b50:
  2754                              <1> 	;-----	PRINTER STATUS
  2755                              <1> B50:
  2756 00005F2C 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2757                              <1> B60:
  2758 00005F2D 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2759                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2760                              <1> 				; POINT TO CONTROL PORT
  2761 00005F31 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2762 00005F32 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2763 00005F33 88C4                <1> 	mov	ah, al		; SAVE
  2764 00005F35 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2765                              <1> B70:
  2766 00005F38 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2767 00005F39 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2768 00005F3B 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2769                              <1> B10:
  2770 00005F3E C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2771                              <1> _b20:
  2772                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2773 00005F3F B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2774                              <1> B20:
  2775 00005F44 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2776 00005F45 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2777 00005F49 EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2778 00005F4A FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2779                              <1> 
  2780                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2781                              <1> B25:
  2782                              <1> 	;-----	WAIT BUSY
  2783                              <1> B35:
  2784 00005F4C EC                  <1> 	in	al, dx		; GET STATUS
  2785 00005F4D 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2786 00005F4F A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2787 00005F51 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2788 00005F53 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2789 00005F58 E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2790                              <1> 
  2791 00005F5A 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2792 00005F5D 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2793 00005F60 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2794                              <1> 
  2795                              <1> B40:				; SEND STROBE PULSE
  2796 00005F62 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2797 00005F64 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2798 00005F66 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2799 00005F67 EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2800                              <1> 	; IODELAY
  2801                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2802                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2803                              <1> 	; NEWIODELAY
  2804 00005F68 E6EB                <1> 	out	0EBh, al
  2805                              <1> 
  2806 00005F6A B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2807 00005F6C EE                  <1> 	out	dx, al
  2808 00005F6D FB                  <1> 	sti			; INTERRUPTS BACK ON
  2809                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2810                              <1> 	;jmp	short B50
  2811 00005F6E EBBD                <1> 	jmp	short B60
  2812                              <1> 
  2813                              <1> _b80:
  2814                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2815                              <1> B80:
  2816 00005F70 50                  <1> 	push	eax		; SAVE (AL)
  2817 00005F71 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2818 00005F75 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2819 00005F77 EE                  <1> 	out	dx, al
  2820                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2821 00005F78 B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2822                              <1> B90:				; INIT_LOOP
  2823                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2824                              <1> 	;jnz	short B90	; INIT_LOOP
  2825 00005F7D E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2826 00005F82 E2F9                <1> 	loop	B90	
  2827 00005F84 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2828 00005F86 EE                  <1> 	out	dx, al
  2829 00005F87 EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2830                              <1> 
  2831                              <1> 
  2832                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2833                              <1> ; -------------------------------------------------------------------
  2834                              <1> ;
  2835                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2836                              <1> ;;65536/30 = 2185
  2837                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2838                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2839                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2840                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2841                              <1> ;
  2842                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2843                              <1> ;
  2844                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2845                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2846                              <1> ;;1,080,000 / 30 = 36,000
  2847                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2848                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2849                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2850                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2851                              <1> ;
  2852                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2853                              <1> 
  2854                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2855                              <1> ; ------------------------------------------
  2856                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2857                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2858                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2859                              <1> ;	OUTPUT: BX:CX destroyed.
  2860                              <1> ;
  2861                              <1> ;	SAVES:	AX (except when NO STACK)
  2862                              <1> ;
  2863                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2864                              <1> ;		used this way, AX is assumed to be destroyed.
  2865                              <1> 
  2866                              <1> WAIT_REFRESH:
  2867                              <1> 	; 12/06/2022
  2868                              <1> 	; Modified for Retro UNIX 386 v1.2
  2869                              <1> 	
  2870                              <1> 	; (wait for 30 micro seconds)
  2871                              <1> 
  2872                              <1> 	SYS1	equ 61h ; PORT_B
  2873                              <1> 
  2874                              <1> WR_SHORT:
  2875 00005F89 50                  <1> 	push	eax
  2876                              <1> WR_STAT_0:
  2877 00005F8A E461                <1> 	in	al, SYS1	; wait for high to low
  2878 00005F8C A810                <1> 	test	al, 10h		; transition on memory
  2879 00005F8E 75FA                <1> 	jnz	short WR_STAT_0 
  2880                              <1> WR_STAT_1:
  2881 00005F90 E461                <1> 	in	al, SYS1
  2882 00005F92 A810                <1> 	test	al, 10h
  2883 00005F94 74FA                <1> 	jz	short WR_STAT_1
  2884 00005F96 58                  <1> 	pop	eax
  2885 00005F97 C3                  <1> 	retn
  2096                                  
  2097                                  ; 07/03/2015
  2098                                  ; Temporary Code
  2099                                  display_disks:
  2100 00005F98 803D[4C630000]00        	cmp 	byte [fd0_type], 0
  2101 00005F9F 7605                    	jna 	short ddsks1
  2102 00005FA1 E87D000000              	call	pdskm
  2103                                  ddsks1:
  2104 00005FA6 803D[4D630000]00        	cmp	byte [fd1_type], 0
  2105 00005FAD 760C                    	jna	short ddsks2
  2106 00005FAF C605[13650000]31        	mov	byte [dskx], '1'
  2107 00005FB6 E868000000              	call	pdskm
  2108                                  ddsks2:
  2109 00005FBB 803D[4E630000]00        	cmp	byte [hd0_type], 0
  2110 00005FC2 7654                    	jna	short ddsk6
  2111 00005FC4 66C705[11650000]68-     	mov	word [dsktype], 'hd'
  2111 00005FCC 64                 
  2112 00005FCD C605[13650000]30        	mov	byte [dskx], '0'
  2113 00005FD4 E84A000000              	call	pdskm
  2114                                  ddsks3:
  2115 00005FD9 803D[4F630000]00        	cmp	byte [hd1_type], 0
  2116 00005FE0 7636                    	jna	short ddsk6
  2117 00005FE2 C605[13650000]31        	mov	byte [dskx], '1'
  2118 00005FE9 E835000000              	call	pdskm
  2119                                  ddsks4:
  2120 00005FEE 803D[50630000]00        	cmp	byte [hd2_type], 0
  2121 00005FF5 7621                    	jna	short ddsk6
  2122 00005FF7 C605[13650000]32        	mov	byte [dskx], '2'
  2123 00005FFE E820000000              	call	pdskm
  2124                                  ddsks5:
  2125 00006003 803D[51630000]00        	cmp	byte [hd3_type], 0
  2126 0000600A 760C                    	jna	short ddsk6
  2127 0000600C C605[13650000]33        	mov	byte [dskx], '3'
  2128 00006013 E80B000000              	call	pdskm
  2129                                  ddsk6:
  2130 00006018 BE[22650000]            	mov	esi, nextline
  2131 0000601D E806000000              	call	pdskml
  2132                                  pdskm_ok:
  2133 00006022 C3                      	retn
  2134                                  pdskm:
  2135 00006023 BE[0F650000]            	mov	esi, dsk_ready_msg
  2136                                  pdskml:	
  2137 00006028 AC                      	lodsb
  2138 00006029 08C0                    	or	al, al
  2139 0000602B 74F5                    	jz	short pdskm_ok
  2140 0000602D 56                      	push	esi
  2141 0000602E 31DB                    	xor	ebx, ebx ; 0
  2142                                  			; Video page 0 (bl=0)
  2143 00006030 B407                    	mov	ah, 07h ; Black background, 
  2144                                  			; light gray forecolor
  2145 00006032 E86AB3FFFF              	call	write_tty
  2146 00006037 5E                      	pop	esi
  2147 00006038 EBEE                    	jmp	short pdskml
  2148                                  
  2149 0000603A 90<rep 6h>              align 16
  2150                                  
  2151                                  gdt:	; Global Descriptor Table
  2152                                  	; (30/07/2015, conforming cs)
  2153                                  	; (26/03/2015)
  2154                                  	; (24/03/2015, tss)
  2155                                  	; (19/03/2015)
  2156                                  	; (29/12/2013)
  2157                                  	;
  2158 00006040 0000000000000000        	dw 0, 0, 0, 0	; NULL descriptor
  2159                                  	; 18/08/2014
  2160                                  			; 08h kernel code segment, base = 00000000h		
  2161 00006048 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2162                                  			; 10h kernel data segment, base = 00000000h	
  2163 00006050 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2164                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2165 00006058 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2166                                  			; 23h user data segment, base address = 400000h ; CORE
  2167 00006060 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2168                                  			; Task State Segment
  2169 00006068 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2170                                  			       ;  no IO permission in ring 3)
  2171                                  gdt_tss0:
  2172 0000606A 0000                    	dw 0 ; TSS base address, bits 0-15 
  2173                                  gdt_tss1:
  2174 0000606C 00                      	db 0 ; TSS base address, bits 16-23 
  2175                                  	      		; 49h	
  2176 0000606D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2177 0000606E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2178                                  gdt_tss2:
  2179 0000606F 00                      	db 0 ; TSS base address, bits 24-31 
  2180                                  
  2181                                  gdt_end:
  2182                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2183                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2184                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2185                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2186                                  
  2187                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2188                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2189                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2190                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2191                                  		; W= Writeable, A= Accessed
  2192                                  	
  2193                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2194                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2195                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2196                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2197                                  
  2198                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2199                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2200                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2201                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2202                                  	
  2203                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2204                                  
  2205                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2206                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2207                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2208                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2209                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2210                                  		; AVL= Available to programmers	
  2211                                  
  2212                                  gdtd:
  2213 00006070 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2214 00006072 [40600000]                      dd gdt			; Address of the GDT
  2215                                  
  2216                                  	; 20/08/2014
  2217                                  idtd:
  2218 00006076 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2219 00006078 [C0650000]                      dd idt			; Address of the IDT
  2220                                  
  2221                                  align 4
  2222                                  	; 21/08/2014
  2223                                  ilist:
  2224                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2225                                  	;
  2226                                  	; Exception list
  2227                                  	; 25/08/2014	
  2228 0000607C [04080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2229 00006080 [0B080000]              	dd	exc1	
  2230 00006084 [12080000]              	dd 	exc2	
  2231 00006088 [19080000]              	dd	exc3	
  2232 0000608C [1D080000]              	dd	exc4	
  2233 00006090 [21080000]              	dd	exc5	
  2234 00006094 [25080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2235 00006098 [29080000]              	dd	exc7	
  2236 0000609C [2D080000]              	dd	exc8	
  2237 000060A0 [31080000]              	dd	exc9	
  2238 000060A4 [35080000]              	dd 	exc10	
  2239 000060A8 [39080000]              	dd	exc11
  2240 000060AC [3D080000]              	dd	exc12
  2241 000060B0 [41080000]              	dd	exc13	; 0Dh, General Protection Fault
  2242 000060B4 [45080000]              	dd 	exc14	; 0Eh, Page Fault
  2243 000060B8 [49080000]              	dd	exc15
  2244 000060BC [4D080000]              	dd	exc16
  2245 000060C0 [51080000]              	dd	exc17
  2246 000060C4 [55080000]              	dd 	exc18
  2247 000060C8 [59080000]              	dd	exc19
  2248 000060CC [5D080000]              	dd 	exc20
  2249 000060D0 [61080000]              	dd	exc21
  2250 000060D4 [65080000]              	dd	exc22
  2251 000060D8 [69080000]              	dd	exc23
  2252 000060DC [6D080000]              	dd 	exc24
  2253 000060E0 [71080000]              	dd	exc25
  2254 000060E4 [75080000]              	dd	exc26
  2255 000060E8 [79080000]              	dd	exc27
  2256 000060EC [7D080000]              	dd 	exc28
  2257 000060F0 [81080000]              	dd	exc29
  2258 000060F4 [85080000]              	dd 	exc30
  2259 000060F8 [89080000]              	dd	exc31
  2260                                  	; Interrupt list
  2261 000060FC [3F060000]              	dd	timer_int	; INT 20h
  2262                                  		;dd	irq0	
  2263 00006100 [430B0000]              	dd	keyb_int	; 27/08/2014
  2264                                  		;dd	irq1
  2265 00006104 [5E070000]              	dd	irq2
  2266                                  		; COM2 int
  2267 00006108 [62070000]              	dd	irq3
  2268                                  		; COM1 int
  2269 0000610C [6D070000]              	dd	irq4
  2270 00006110 [78070000]              	dd	irq5
  2271                                  ;DISKETTE_INT: ;06/02/2015
  2272 00006114 [CC1F0000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2273                                  		;dd	irq6
  2274                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2275                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2276 00006118 [F40A0000]              	dd	default_irq7	; 25/02/2015
  2277                                  		;dd	irq7
  2278                                  ; Real Time Clock Interrupt
  2279 0000611C [92090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2280                                  		;dd	irq8	; INT 28h
  2281 00006120 [88070000]              	dd	irq9
  2282 00006124 [8C070000]              	dd	irq10
  2283 00006128 [90070000]              	dd	irq11
  2284 0000612C [94070000]              	dd	irq12
  2285 00006130 [98070000]              	dd	irq13
  2286                                  ;HDISK_INT1:  ;06/02/2015 	
  2287 00006134 [9D240000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2288                                  		;dd	irq14
  2289                                  ;HDISK_INT2:  ;06/02/2015
  2290 00006138 [C0240000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2291                                  		;dd	irq15	; INT 2Fh
  2292                                  		; 14/08/2015
  2293 0000613C [69310000]              	dd	sysent		; INT 30h (system calls)
  2294                                  	
  2295                                  	;dd	ignore_int
  2296 00006140 00000000                	dd	0
  2297                                  
  2298                                  ;;;
  2299                                  ;;; 11/03/2015
  2300                                  %include 'kybdata.s'	; KEYBOARD (BIOS) DATA
  2301                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.2.2) - KYBDATA.INC
  2302                              <1> ; Last Modification: 11/06/2022
  2303                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2304                              <1> ;
  2305                              <1> ; ///////// KEYBOARD DATA ///////////////
  2306                              <1> 
  2307                              <1> ; 11/03/2015
  2308                              <1> ; 05/12/2014
  2309                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2310                              <1> ; 03/06/86  KEYBOARD BIOS
  2311                              <1> 
  2312                              <1> ;---------------------------------------------------------------------------------
  2313                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2314                              <1> ;---------------------------------------------------------------------------------
  2315                              <1> 
  2316                              <1> ;-----	TABLES FOR ALT CASE ------------
  2317                              <1> ;-----	ALT-INPUT-TABLE 
  2318 00006144 524F50514B          <1> K30:	db	82,79,80,81,75
  2319 00006149 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2320                              <1> ;-----	SUPER-SHIFT-TABLE 
  2321 0000614E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2322 00006154 161718191E1F        <1> 	db	22,23,24,25,30,31
  2323 0000615A 202122232425        <1> 	db	32,33,34,35,36,37
  2324 00006160 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2325 00006166 3132                <1> 	db	49,50
  2326                              <1> 
  2327                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2328                              <1> ;-----	KEY_TABLE 
  2329 00006168 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2330 00006169 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2331 0000616E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2332                              <1> _K6L    equ     $-_K6
  2333                              <1> 
  2334                              <1> ;-----	MASK_TABLE
  2335 00006170 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2336 00006171 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2337 00006176 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2338                              <1> 
  2339                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2340 00006178 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2341 0000617E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2342                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2343 00006184 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 11/06/2022
  2344 0000618A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2345 00006190 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2346 00006196 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2347 0000619C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2348 000061A2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2349 000061A8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2350 000061AE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2351                              <1> 	;				;----- FUNCTIONS ------		
  2352 000061B2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2353 000061B8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2354 000061BE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2355 000061C4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2356 000061CA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2357                              <1> 
  2358                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2359 000061D0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2359 000061D9 39302D3D0809        <1>
  2360 000061DF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2360 000061E8 705B5D0DFF61736466- <1>
  2360 000061F1 67686A6B6C3B27      <1>
  2361 000061F8 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2361 00006201 6D2C2E2FFF2AFF20FF  <1>
  2362                              <1> ;-----	LC TABLE SCAN
  2363 0000620A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2364 0000620F 4041424344          <1> 	db	64,65,66,67,68
  2365 00006214 FFFF                <1> 	db	-1,-1			; NL, SL
  2366                              <1> 
  2367                              <1> ;-----	KEYPAD TABLE
  2368 00006216 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2369 0000621C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2370 00006223 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2371                              <1> 
  2372                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2373 00006228 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2373 00006231 28295F2B0800        <1>
  2374 00006237 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2374 00006240 507B7D0DFF41534446- <1>
  2374 00006249 47484A4B4C3A22      <1>
  2375 00006250 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2375 00006259 4D3C3E3FFF2AFF20FF  <1>
  2376                              <1> ;-----	UC TABLE SCAN
  2377 00006262 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2378 00006267 595A5B5C5D          <1> 	db	89,90,91,92,93
  2379 0000626C FFFF                <1> 	db	-1,-1			; NL, SL
  2380                              <1> 
  2381                              <1> ;-----	NUM STATE TABLE
  2382 0000626E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2382 00006277 3233302E            <1>
  2383                              <1> 	;
  2384 0000627B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2385                              <1> 
  2386                              <1> Align	4
  2387                              <1> ;----------------------------------------
  2388                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2389                              <1> ;----------------------------------------
  2390 00006280 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2391 00006281 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2392                              <1> 				; (29h default setting for video mode 3)
  2393                              <1> 				; Mode Select register Bits
  2394                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2395                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2396                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2397                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2398                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2399                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2400                              <1> 				;   BIT 6, 7 - Not Used
  2401                              <1> 
  2402                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2403                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2404                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2405                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2406                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2407                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2408                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2409                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2410                              <1> ; Mode & 37h = Video signal OFF
  2411                              <1> 			
  2412                              <1> 
  2413                              <1> ; 26/08/2014
  2414                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2415                              <1> ; Derived from IBM "pc-at" 
  2416                              <1> ; rombios source code (06/10/1985)
  2417                              <1> ; 'dseg.inc'
  2418                              <1> 
  2419                              <1> ;---------------------------------------;
  2420                              <1> ;	SYSTEM DATA AREA		;
  2421                              <1> ;----------------------------------------
  2422 00006282 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2423                              <1> 
  2424                              <1> ;----------------------------------------
  2425                              <1> ;	KEYBOARD DATA AREAS		;
  2426                              <1> ;----------------------------------------
  2427                              <1> 
  2428 00006283 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2429 00006284 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2430 00006285 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2431 00006286 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2432 00006287 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2433 00006288 [98620000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2434 0000628C [B8620000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2435 00006290 [98620000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2436 00006294 [98620000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2437                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2438 00006298 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2439                              <1> 
  2440                              <1> ; /// End Of KEYBOARD DATA ///
  2301                                  %include 'vidata.s'	; VIDEO (BIOS) DATA
  2302                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2303                              <1> ; Last Modification: 11/03/2015
  2304                              <1> ;		    (Data section for 'VIDEO.INC')	
  2305                              <1> ;
  2306                              <1> ; ///////// VIDEO DATA ///////////////
  2307                              <1> 
  2308                              <1> video_params:
  2309                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2310                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2311                              <1> 	; VIDEO MODE 3
  2312 000062B8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2313 000062BF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2314 000062C4 00000000            <1> 	db	0,0,0,0
  2315                              <1> 
  2316                              <1> ; /// End Of VIDEO DATA ///
  2302                                  %include 'diskdata.s'	; DISK (BIOS) DATA (initialized)
  2303                              <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - DISKBSS.INC
  2304                              <1> ; Last Modification: 12/07/2022 
  2305                              <1> ; *****************************************************************************
  2306                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2307                              <1> ; *****************************************************************************
  2308                              <1> ; Ref: Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKDATA.INC - 11/07/2022
  2309                              <1> 
  2310                              <1> ;----------------------------------------
  2311                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2312                              <1> ;	REFERENCED BY POST & BIOS	:
  2313                              <1> ;----------------------------------------
  2314                              <1> 
  2315 000062C8 [2B630000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2316                              <1> 
  2317                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2318                              <1> ;----------------------------------------------------------------
  2319                              <1> ; DISK_BASE							:
  2320                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2321                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2322                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2323                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2324                              <1> ;----------------------------------------------------------------
  2325                              <1> 
  2326                              <1> ;DISK_BASE:	
  2327                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2328                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2329                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2330                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2331                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2332                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2333                              <1> ;	DB	01BH		; GAP LENGTH
  2334                              <1> ;	DB	0FFH		; DTL
  2335                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2336                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2337                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2338                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2339                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2340                              <1> 
  2341                              <1> ;----------------------------------------
  2342                              <1> ;	ROM BIOS DATA AREAS		:
  2343                              <1> ;----------------------------------------
  2344                              <1> 
  2345                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2346                              <1> 
  2347                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2348                              <1> 
  2349                              <1> ;----------------------------------------
  2350                              <1> ;	DISKETTE DATA AREAS		:
  2351                              <1> ;----------------------------------------
  2352                              <1> 
  2353                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2354                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2355                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2356                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2357                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2358                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2359                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2360                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2361                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2362                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2363                              <1> 
  2364                              <1> ;----------------------------------------
  2365                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2366                              <1> ;----------------------------------------
  2367                              <1> 
  2368                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2369                              <1> 
  2370                              <1> ;----------------------------------------
  2371                              <1> ;	TIMER DATA AREA 		:
  2372                              <1> ;----------------------------------------
  2373                              <1> 
  2374                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2375                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2376                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2377                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2378                              <1> 
  2379                              <1> ;----------------------------------------
  2380                              <1> ;	ADDITIONAL MEDIA DATA		:
  2381                              <1> ;----------------------------------------
  2382                              <1> 
  2383                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2384                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2385                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2386                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2387                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2388                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2389                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2390                              <1> 
  2391                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2392                              <1> 
  2393                              <1> ;--------------------------------------------------------
  2394                              <1> ;	DRIVE TYPE TABLE				:
  2395                              <1> ;--------------------------------------------------------
  2396                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2397                              <1> DR_TYPE:
  2398 000062CC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2399                              <1>                 ;DW      MD_TBL1
  2400 000062CD [EA620000]          <1> 		dd	MD_TBL1
  2401 000062D1 82                  <1> 		DB	02+BIT7ON
  2402                              <1> 		;DW      MD_TBL2
  2403 000062D2 [F7620000]          <1>                 dd      MD_TBL2
  2404 000062D6 02                  <1> DR_DEFAULT:	DB	02
  2405                              <1>                 ;DW      MD_TBL3
  2406 000062D7 [04630000]          <1> 		dd      MD_TBL3
  2407 000062DB 03                  <1> 		DB	03
  2408                              <1>                 ;DW      MD_TBL4
  2409 000062DC [11630000]          <1> 		dd      MD_TBL4
  2410 000062E0 84                  <1> 		DB	04+BIT7ON
  2411                              <1>                 ;DW      MD_TBL5
  2412 000062E1 [1E630000]          <1> 		dd      MD_TBL5
  2413 000062E5 04                  <1> 		DB	04
  2414                              <1>                 ;DW      MD_TBL6
  2415 000062E6 [2B630000]          <1> 		dd      MD_TBL6
  2416                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2417                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2418                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2419                              <1> ;--------------------------------------------------------
  2420                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2421                              <1> ;--------------------------------------------------------
  2422                              <1> ;--------------------------------------------------------
  2423                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2424                              <1> ;--------------------------------------------------------
  2425                              <1> MD_TBL1:        
  2426 000062EA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2427 000062EB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2428 000062EC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2429 000062ED 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2430 000062EE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2431 000062EF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2432 000062F0 FF                  <1> 	DB	0FFH		; DTL
  2433 000062F1 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2434 000062F2 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2435 000062F3 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2436 000062F4 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2437 000062F5 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2438 000062F6 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2439                              <1> ;--------------------------------------------------------
  2440                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2441                              <1> ;--------------------------------------------------------
  2442                              <1> MD_TBL2:        
  2443 000062F7 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2444 000062F8 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2445 000062F9 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2446 000062FA 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2447 000062FB 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2448 000062FC 2A                  <1> 	DB	02AH		; GAP LENGTH
  2449 000062FD FF                  <1> 	DB	0FFH		; DTL
  2450 000062FE 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2451 000062FF F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2452 00006300 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2453 00006301 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2454 00006302 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2455 00006303 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2456                              <1> ;--------------------------------------------------------
  2457                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2458                              <1> ;--------------------------------------------------------
  2459                              <1> MD_TBL3:
  2460 00006304 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2461 00006305 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2462 00006306 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2463 00006307 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2464 00006308 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2465 00006309 1B                  <1> 	DB	01BH		; GAP LENGTH
  2466 0000630A FF                  <1> 	DB	0FFH		; DTL
  2467 0000630B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2468 0000630C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2469 0000630D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2470 0000630E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2471 0000630F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2472 00006310 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2473                              <1> ;--------------------------------------------------------
  2474                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2475                              <1> ;--------------------------------------------------------
  2476                              <1> MD_TBL4:
  2477 00006311 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2478 00006312 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2479 00006313 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2480 00006314 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2481 00006315 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2482 00006316 2A                  <1> 	DB	02AH		; GAP LENGTH
  2483 00006317 FF                  <1> 	DB	0FFH		; DTL
  2484 00006318 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2485 00006319 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2486 0000631A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2487 0000631B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2488 0000631C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2489 0000631D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2490                              <1> ;--------------------------------------------------------
  2491                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2492                              <1> ;--------------------------------------------------------
  2493                              <1> MD_TBL5:
  2494 0000631E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2495 0000631F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2496 00006320 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2497 00006321 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2498 00006322 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2499 00006323 2A                  <1> 	DB	02AH		; GAP LENGTH
  2500 00006324 FF                  <1> 	DB	0FFH		; DTL
  2501 00006325 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2502 00006326 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2503 00006327 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2504 00006328 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2505 00006329 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2506 0000632A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2507                              <1> ;--------------------------------------------------------
  2508                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2509                              <1> ;--------------------------------------------------------
  2510                              <1> MD_TBL6:
  2511 0000632B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2512 0000632C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2513 0000632D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2514 0000632E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2515 0000632F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2516 00006330 1B                  <1> 	DB	01BH		; GAP LENGTH
  2517 00006331 FF                  <1> 	DB	0FFH		; DTL
  2518 00006332 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2519 00006333 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2520 00006334 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2521 00006335 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2522 00006336 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2523 00006337 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2524                              <1> 
  2525                              <1> 
  2526                              <1> ; << diskette.inc >>
  2527                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2528                              <1> ;
  2529                              <1> ;----------------------------------------
  2530                              <1> ;	ROM BIOS DATA AREAS		:
  2531                              <1> ;----------------------------------------
  2532                              <1> 
  2533                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2534                              <1> 
  2535                              <1> ;----------------------------------------
  2536                              <1> ;	FIXED DISK DATA AREAS		:
  2537                              <1> ;----------------------------------------
  2538                              <1> 
  2539                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2540                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2541                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2542                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2543                              <1> 
  2544                              <1> ;----------------------------------------
  2545                              <1> ;	ADDITIONAL MEDIA DATA		:
  2546                              <1> ;----------------------------------------
  2547                              <1> 
  2548                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2549                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2550                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2551                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2552                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2553                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2554                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2555                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2556                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2557                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2558                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2559                              <1> 
  2560                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2561                              <1> ;
  2562                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2563                              <1> 
  2564                              <1> ERR_TBL:
  2565 00006338 E0                  <1> 	db	NO_ERR
  2566 00006339 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2567 0000633D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2568                              <1> 
  2569                              <1> ; 11/07/2022
  2570                              <1> ; 17/12/2014 (mov ax, [cfd])
  2571                              <1> ; 11/12/2014
  2572                              <1> ;cfd:		db 0			; current floppy drive (for GET_PARM)
  2573                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2574                              <1> ;pfd:		db 1			; previous floppy drive (for GET_PARM)
  2575                              <1> 					; (initial value of 'pfd 
  2576                              <1> 					; must be different then 'cfd' value
  2577                              <1> 					; to force updating/initializing
  2578                              <1> 					; current drive parameters) 
  2579                              <1> 
  2580                              <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2581 00006341 FF                  <1> pfd:		db 0FFh
  2582                              <1> 
  2583                              <1> align 2
  2584                              <1> 
  2585 00006342 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2586                              <1> 			      ; (170h)
  2587 00006344 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2588                              <1> 
  2589                              <1> ; 05/01/2015 
  2590 00006346 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2591                              <1> 
  2592                              <1> ; *****************************************************************************
  2303                                  ;;;
  2304                                  
  2305 00006347 90                      align 2
  2306                                  
  2307                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2308 00006348 00                      boot_drv:    db 0  ; boot drive number (physical)
  2309                                  ; 24/11/2014
  2310 00006349 00                      drv:	     db 0 
  2311 0000634A 00                      last_drv:    db 0  ; last hdd
  2312 0000634B 00                      hdc:         db 0  ; number of hard disk drives
  2313                                  		     ; (present/detected)
  2314                                  ;
  2315                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2316                                  ; Physical drive type & flags
  2317 0000634C 00                      fd0_type:    db 0  ; floppy drive type
  2318 0000634D 00                      fd1_type:    db 0    ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2319                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2320                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2321                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2322                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2323 0000634E 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 - present flag)
  2324 0000634F 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 - present flag)
  2325 00006350 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 - present flag)
  2326 00006351 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 - present flag)
  2327                                  		     ; bit 0 - Fixed disk access subset supported
  2328                                  		     ; bit 1 - Drive locking and ejecting
  2329                                  		     ; bit 2 - Enhanced disk drive support
  2330                                  		     ; bit 3 - Reserved (64 bit EDD support)
  2331                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2332                                  		     ; will interpret it as 'LBA ready'!)		
  2333                                  
  2334                                  ; 12/07/2022
  2335                                  ; (drv.cylinders, drv.spt, drv.spt will not be used now on)
  2336                                  ; ('diskio.inc')
  2337                                  ; ((spt and heads and cylinder counts will be taken from DPT))
  2338                                  
  2339                                  ; 11/03/2015 - 10/07/2015
  2340                                  ;drv.cylinders: dw 0,0,0,0,0,0,0
  2341                                  ;drv.heads:     dw 0,0,0,0,0,0,0
  2342                                  ;drv.spt:       dw 0,0,0,0,0,0,0
  2343                                  ; 12/07/2022 - 11/03/2015
  2344 00006352 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2344 0000635B 000000000000000000-
  2344 00006364 000000000000000000-
  2344 0000636D 00                 
  2345 0000636E 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2346 00006375 00000000000000          drv.error:     db 0,0,0,0,0,0,0
  2347                                  ;
  2348                                  
  2349                                  ; 27/08/2014
  2350                                  scr_row:
  2351 0000637C E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2352                                  scr_col:
  2353 00006380 00000000                	dd 0
  2354                                  
  2355                                  ;; 14/08/2015
  2356                                  ;;msgPM:
  2357                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2358                                  msgKVER:
  2359                                  	;;;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [18/04/2022]", 0
  2360                                  	;;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.1 [08/06/2022]", 0
  2361                                  	;db "Retro UNIX 386 v1.2 - Kernel v0.2.2.2 [14/06/2022]", 0
  2362 00006384 526574726F20554E49-     	db "Retro UNIX 386 v1.2 - Kernel v0.2.2.3 [16/07/2022]", 0
  2362 0000638D 58203338362076312E-
  2362 00006396 32202D204B65726E65-
  2362 0000639F 6C2076302E322E322E-
  2362 000063A8 33205B31362F30372F-
  2362 000063B1 323032325D00       
  2363                                  
  2364 000063B7 90                      align 2
  2365                                  
  2366                                  ; 20/08/2014
  2367                                    ; /* This is the default interrupt "handler" :-) */ 
  2368                                    ; Linux v0.12 (head.s)
  2369                                  int_msg:
  2370 000063B8 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2370 000063C1 6E7465727275707420-
  2370 000063CA 212000             
  2371                                  
  2372 000063CD 90                      align 2  
  2373                                  
  2374                                  ; 21/08/2014
  2375                                  timer_msg:
  2376 000063CE 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2376 000063D7 542032306829202120-
  2376 000063E0 54696D657220496E74-
  2376 000063E9 657272757074203A20 
  2377                                  tcountstr:
  2378 000063F2 303030303020            	db "00000 "
  2379 000063F8 00                      	db 0
  2380                                  
  2381 000063F9 90                      align 2
  2382                                  	; 21/08/2014
  2383                                  exc_msg:
  2384 000063FA 435055206578636570-     	db "CPU exception ! "
  2384 00006403 74696F6E202120     
  2385                                  excnstr: 		; 25/08/2014
  2386 0000640A 3F3F68202045495020-     	db "??h", "  EIP : "
  2386 00006413 3A20               
  2387                                  EIPstr: ; 29/08/2014
  2388 00006415 00<rep Ch>              	times 12 db 0
  2389                                  rtc_msg:
  2390 00006421 5265616C2054696D65-     	db "Real Time Clock - "
  2390 0000642A 20436C6F636B202D20 
  2391                                  datestr:
  2392 00006433 30302F30302F303030-     	db "00/00/0000"
  2392 0000643C 30                 
  2393 0000643D 20                      	db " "
  2394                                  daystr:
  2395 0000643E 44415920                	db "DAY "
  2396                                  timestr:	
  2397 00006442 30303A30303A3030                db "00:00:00"
  2398 0000644A 20                      	db " "
  2399 0000644B 00                      	db 0 
  2400                                  
  2401                                  daytmp:
  2402                                  	; 28/02/2015
  2403 0000644C 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2403 00006455 4F4E20545545205745-
  2403 0000645E 442054485520465249-
  2403 00006467 2053415420         
  2404                                  
  2405 0000646C FF                      ptime_seconds: db 0FFh
  2406                                  
  2407                                  	; 23/02/2015
  2408                                  	; 25/08/2014
  2409                                  ;scounter:
  2410                                  ;	db 5
  2411                                  ;	db 19
  2412                                  
  2413                                  ; 28/11/2021
  2414                                  ;; 05/11/2014
  2415                                  ;msg_out_of_memory:
  2416                                  ;	db 	07h, 0Dh, 0Ah
  2417                                  ;	db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2418                                  ; 	db	0Dh, 0Ah, 0
  2419                                  	;
  2420                                  setup_error_msg:
  2421 0000646D 0D0A                    	db 0Dh, 0Ah
  2422 0000646F 4469736B2053657475-     	db 'Disk Setup Error!' 
  2422 00006478 70204572726F7221   
  2423 00006480 0D0A00                  	db 0Dh, 0Ah,0
  2424                                  
  2425                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2426                                  ;crt_ulc: db 0 ; upper left column (for scroll) 
  2427                                  ;	  db 0 ; upper left row (for scroll)	
  2428                                  
  2429                                  ;crt_lrc: db 79 ; lower right column (for scroll) 
  2430                                  ;	  db 24 ; lower right row (for scroll)
  2431                                  
  2432                                  ; 06/11/2014 (Temporary Data)
  2433                                  ; Memory Information message
  2434                                  ; 14/08/2015
  2435                                  msg_memory_info:
  2436 00006483 07                      	db	07h
  2437 00006484 0D0A                    	db	0Dh, 0Ah
  2438                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2439 00006486 546F74616C206D656D-     	db	"Total memory : "
  2439 0000648F 6F7279203A20       
  2440                                  mem_total_b_str: ; 10 digits
  2441 00006495 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2441 0000649E 302062797465730D0A 
  2442 000064A7 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2442 000064B0 202020202020202020 
  2443                                  mem_total_p_str: ; 7 digits
  2444 000064B9 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2444 000064C2 616765730D0A       
  2445 000064C8 0D0A                    	db 	0Dh, 0Ah
  2446 000064CA 46726565206D656D6F-     	db	"Free memory  : "
  2446 000064D3 727920203A20       
  2447                                  free_mem_b_str:  ; 10 digits
  2448 000064D9 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2448 000064E2 3F2062797465730D0A 
  2449 000064EB 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2449 000064F4 202020202020202020 
  2450                                  free_mem_p_str:  ; 7 digits
  2451 000064FD 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2451 00006506 616765730D0A       
  2452 0000650C 0D0A00                  	db	0Dh, 0Ah, 0
  2453                                  
  2454                                  dsk_ready_msg:
  2455 0000650F 0D0A                    	db 	0Dh, 0Ah
  2456                                  dsktype:
  2457 00006511 6664                    	db	'fd'
  2458                                  dskx:
  2459 00006513 30                      	db	'0'
  2460 00006514 20                      	db	20h
  2461 00006515 697320524541445920-     	db 	'is READY ...'
  2461 0000651E 2E2E2E             
  2462 00006521 00                      	db 	0
  2463                                  nextline:
  2464 00006522 0D0A00                  	db 	0Dh, 0Ah, 0
  2465                                  
  2466                                  ; KERNEL - SYSINIT Messages
  2467                                  ; 24/08/2015
  2468                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2469                                  ; 14/07/2013
  2470                                  ;kernel_init_err_msg:
  2471                                  ;	db 0Dh, 0Ah
  2472                                  ;	db 07h
  2473                                  ;	db 'Kernel initialization ERROR !'
  2474                                  ;	db 0Dh, 0Ah, 0 
  2475                                  ; 24/08/2015
  2476                                  ;;; (temporary kernel init message has been removed
  2477                                  ;;;  from 'sys_init' code)
  2478                                  ;kernel_init_ok_msg: 
  2479                                  ;	db 0Dh, 0Ah
  2480                                  ;	db 07h
  2481                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2482                                  ;	db 0Dh, 0Ah
  2483                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2484                                  ;	db 0Dh, 0Ah, 0
  2485                                  panic_msg:
  2486 00006525 0D0A07                  	db 0Dh, 0Ah, 07h
  2487 00006528 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2487 00006531 726E656C2050616E69-
  2487 0000653A 632021             
  2488 0000653D 0D0A00                  	db 0Dh, 0Ah, 0
  2489                                  etc_init_err_msg:
  2490 00006540 0D0A                    	db 0Dh, 0Ah
  2491 00006542 07                      	db 07h
  2492 00006543 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2492 0000654C 74632F696E69742021-
  2492 00006555 3F                 
  2493 00006556 0D0A00                  	db 0Dh, 0Ah, 0
  2494                                  
  2495                                  ; 10/05/2015
  2496                                  badsys_msg:
  2497 00006559 0D0A                    	db 0Dh, 0Ah
  2498 0000655B 07                      	db 07h
  2499 0000655C 496E76616C69642053-     	db 'Invalid System Call !'
  2499 00006565 797374656D2043616C-
  2499 0000656E 6C2021             
  2500 00006571 0D0A                    	db 0Dh, 0Ah
  2501 00006573 4541583A20              	db 'EAX: '
  2502                                  bsys_msg_eax:
  2503 00006578 303030303030303068      	db '00000000h'
  2504 00006581 0D0A                    	db 0Dh, 0Ah
  2505 00006583 4549503A20              	db 'EIP: '
  2506                                  bsys_msg_eip:
  2507 00006588 303030303030303068      	db '00000000h' 
  2508 00006591 0D0A00                  	db 0Dh, 0Ah, 0
  2509                                  
  2510                                  BSYS_M_SIZE equ $ - badsys_msg
  2511                                  
  2512                                  align 2
  2513                                  
  2514                                  ; EPOCH Variables
  2515                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2516                                  ; 09/04/2013 epoch variables
  2517                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2518                                  ;
  2519 00006594 B207                    year: 	dw 1970
  2520                                  ;month: dw 1
  2521                                  ;day: 	dw 1
  2522                                  ;hour: 	dw 0
  2523                                  ;minute: dw 0
  2524                                  ;second: dw 0
  2525                                  ; 02/06/2022
  2526 00006596 01                      month:	db 1
  2527 00006597 01                      day:	db 1
  2528 00006598 01                      hour:	db 1
  2529 00006599 01                      minute: db 1
  2530 0000659A 01                      second:	db 1
  2531 0000659B 01                      	db 1
  2532                                  
  2533                                  DMonth:
  2534 0000659C 0000                    	dw 0
  2535 0000659E 1F00                    	dw 31
  2536 000065A0 3B00                    	dw 59
  2537 000065A2 5A00                    	dw 90
  2538 000065A4 7800                    	dw 120
  2539 000065A6 9700                    	dw 151
  2540 000065A8 B500                    	dw 181
  2541 000065AA D400                    	dw 212
  2542 000065AC F300                    	dw 243
  2543 000065AE 1101                    	dw 273
  2544 000065B0 3001                    	dw 304
  2545 000065B2 4E01                    	dw 334
  2546                                  
  2547                                  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2548                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2549 000065B4 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2550                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2551 000065B6 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2552 000065B8 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2553                                  		   ;   between 16 MB and 4 GB.
  2554 000065BA 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2555                                  
  2556                                  ; 01/01/2022
  2557                                  KEND:
  2558                                  
  2559 000065BC 90<rep 4h>              align 16
  2560                                  
  2561                                  bss_start:
  2562                                  
  2563                                  ABSOLUTE bss_start
  2564                                  
  2565                                  	; 11/03/2015
  2566                                  	; Interrupt Descriptor Table (20/08/2014)
  2567                                  idt:
  2568 000065C0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2569                                  idt_end:
  2570                                  
  2571                                  ;alignb 4
  2572                                  
  2573                                  task_state_segment:
  2574                                  	; 24/03/2015
  2575 000067C0 ????                    tss.link:   resw 1
  2576 000067C2 ????                    	    resw 1
  2577                                  ; tss offset 4	
  2578 000067C4 ????????                tss.esp0:   resd 1
  2579 000067C8 ????                    tss.ss0:    resw 1
  2580 000067CA ????                    	    resw 1	
  2581 000067CC ????????                tss.esp1:   resd 1
  2582 000067D0 ????                    tss.ss1:    resw 1
  2583 000067D2 ????                    	    resw 1 	
  2584 000067D4 ????????                tss.esp2:   resd 1
  2585 000067D8 ????                    tss.ss2:    resw 1
  2586 000067DA ????                    	    resw 1
  2587                                  ; tss offset 28
  2588 000067DC ????????                tss.CR3:    resd 1
  2589 000067E0 ????????                tss.eip:    resd 1
  2590 000067E4 ????????                tss.eflags: resd 1
  2591                                  ; tss offset 40
  2592 000067E8 ????????                tss.eax:    resd 1		 		
  2593 000067EC ????????                tss.ecx:    resd 1
  2594 000067F0 ????????                tss.edx:    resd 1
  2595 000067F4 ????????                tss.ebx:    resd 1
  2596 000067F8 ????????                tss.esp:    resd 1
  2597 000067FC ????????                tss.ebp:    resd 1
  2598 00006800 ????????                tss.esi:    resd 1
  2599 00006804 ????????                tss.edi:    resd 1
  2600                                  ; tss offset 72
  2601 00006808 ????                    tss.ES:     resw 1
  2602 0000680A ????                    	    resw 1	
  2603 0000680C ????                    tss.CS:	    resw 1
  2604 0000680E ????                    	    resw 1
  2605 00006810 ????                    tss.SS:	    resw 1
  2606 00006812 ????                    	    resw 1
  2607 00006814 ????                    tss.DS:	    resw 1
  2608 00006816 ????                    	    resw 1
  2609 00006818 ????                    tss.FS:	    resw 1
  2610 0000681A ????                    	    resw 1
  2611 0000681C ????                    tss.GS:	    resw 1
  2612 0000681E ????                    	    resw 1		
  2613 00006820 ????                    tss.LDTR:   resw 1
  2614 00006822 ????                    	    resw 1
  2615                                  ; tss offset 100		
  2616 00006824 ????                    	    resw 1		
  2617 00006826 ????                    tss.IOPB:   resw 1
  2618                                  ; tss offset 104 
  2619                                  tss_end:
  2620                                  
  2621 00006828 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2622                                  		    ;  (Physical address = Virtual address)	 	
  2623 0000682C ????????                memory_size: resd 1 ; memory size in pages
  2624 00006830 ????????                free_pages:  resd 1 ; number of free pages		
  2625 00006834 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2626                                  		    ;   first free page search
  2627 00006838 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2628                                  		    ;   next free page search will be
  2629                                  		    ;   stopped after it. (end of M.A.T.)
  2630 0000683C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2631                                  		    ; first free page search
  2632                                  		    ;   will be started on it. (for user)
  2633 00006840 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2634                                  
  2635                                  ;;;
  2636                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2637                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2638 00006844 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2639                                  			  ; NOTE: active page only
  2640 00006846 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2641                                  active_page: 
  2642 00006856 ??                      ptty: 	     resb 1 	  ; current tty
  2643                                  ; 01/07/2015
  2644 00006857 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2645                                  ; 26/10/2015
  2646                                  ; 07/09/2014
  2647 00006858 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2648                                  
  2649                                  ; 21/08/2014
  2650 0000686C ????????                tcount:	     resd 1
  2651                                  
  2652                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2653 00006870 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2654                                  
  2655                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2656                                  ; (open mode locks for pseudo TTYs)
  2657                                  ; [ major tty locks (return error in any conflicts) ]
  2658 00006874 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2659                                  
  2660                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2661                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2662 00006888 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2663                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2664                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2665                                  ;; 0 means serial port is not available 
  2666                                  ;;comprm: ; 25/06/2014
  2667 00006892 ??                      com1p:       resb 1  ;;0E3h
  2668 00006893 ??                      com2p:       resb 1  ;;0E3h
  2669                                  
  2670                                  ; 17/11/2015
  2671                                  ; request for response (from the terminal)	
  2672 00006894 ????                    req_resp:    resw 1 			
  2673                                  ; 07/11/2015
  2674 00006896 ??                      ccomport:    resb 1 ; current COM (serial) port
  2675                                  		    ; (0= COM1, 1= COM2)
  2676                                  ; 09/11/2015
  2677 00006897 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2678                                  ; 07/11/2015
  2679 00006898 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2680 0000689A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2681                                  
  2682                                  ; 23/10/2015
  2683                                  ; SERIAL PORTS - COMMUNICATION MODES
  2684                                  ; (Retro UNIX 386 v1 feature only!)
  2685                                  ; 0 - command mode (default/initial mode)
  2686                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2687                                  ;;; communication modes for future versions:  
  2688                                  ; // 2 - keyboard mode (ascii+scancode input)
  2689                                  ; // 3 - mouse mode
  2690                                  ; // 4 - device control (output) mode
  2691                                  ; VALID COMMANDS for current version:
  2692                                  ; 	'LOGIN'
  2693                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2694                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2695                                  ;  Login response: db 0FFh, 'login', 0
  2696                                  ;	 ("login request accepted, wait for login prompt") 
  2697                                  ; When a login requests is received and acknowledged (by
  2698                                  ; serial port interrupt handler (communication procedure),
  2699                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2700                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2701                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2702                                  ; 
  2703                                  ; 'sys connect' system call is used to change communication mode
  2704                                  ; except 'LOGIN' command which is used to start terminal mode
  2705                                  ; by using (COM port) terminal.
  2706                                  
  2707                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2708                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2709                                  ;com1mode:    resb 1 ; communication mode for COM1
  2710                                  ;com1com:     resb 1 ; communication command for COM1
  2711                                  ;com2mode:    resb 1 ; communication mode for COM1
  2712                                  ;com2com      resb 1 ; communication command for COM1
  2713                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2714                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2715                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2716                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2717                                  
  2718                                  ; 22/08/2014 (RTC)
  2719                                  ; (Packed BCD)
  2720 0000689C ??                      time_seconds: resb 1
  2721 0000689D ??                      time_minutes: resb 1
  2722 0000689E ??                      time_hours:   resb 1
  2723 0000689F ??                      date_wday:    resb 1
  2724 000068A0 ??                      date_day:     resb 1
  2725 000068A1 ??                      date_month:   resb 1			
  2726 000068A2 ??                      date_year:    resb 1
  2727 000068A3 ??                      date_century: resb 1
  2728                                  
  2729                                  %include 'diskbss.s' ; UNINITIALIZED DISK (BIOS) DATA
  2730                              <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - DISKBSS.INC
  2731                              <1> ; Last Modification: 12/07/2022 
  2732                              <1> ; *****************************************************************************
  2733                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC')
  2734                              <1> ; *****************************************************************************
  2735                              <1> ; Ref: Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKBSS.INC - 10/07/2022
  2736                              <1>  
  2737                              <1> 
  2738                              <1> alignb 2
  2739                              <1> 
  2740                              <1> ;----------------------------------------
  2741                              <1> ;	TIMER DATA AREA 		:
  2742                              <1> ;----------------------------------------
  2743                              <1> 
  2744                              <1> TIMER_LH:	; 16/02/205
  2745 000068A4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2746 000068A6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2747 000068A8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2748                              <1> 
  2749                              <1> ;----------------------------------------
  2750                              <1> ;	DISKETTE DATA AREAS		:
  2751                              <1> ;----------------------------------------
  2752                              <1> 
  2753 000068A9 ??                  <1> SEEK_STATUS:	resb	1
  2754 000068AA ??                  <1> MOTOR_STATUS:	resb	1
  2755 000068AB ??                  <1> MOTOR_COUNT:	resb	1
  2756 000068AC ??                  <1> DSKETTE_STATUS:	resb	1
  2757 000068AD ??????????????      <1> NEC_STATUS:	resb	7
  2758                              <1> 
  2759                              <1> ;----------------------------------------
  2760                              <1> ;	ADDITIONAL MEDIA DATA		:
  2761                              <1> ;----------------------------------------
  2762                              <1> 
  2763 000068B4 ??                  <1> LASTRATE:	resb 	1
  2764 000068B5 ??                  <1> HF_STATUS:	resb 	1
  2765                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2766 000068B6 ??                  <1> HF_INT_FLAG:	resb	1
  2767                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2768                              <1> ;DSK_STATE:	resb 	4
  2769 000068B7 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2770 000068B9 ????                <1> DSK_TRK:	resb 	2
  2771                              <1> 
  2772                              <1> ;----------------------------------------
  2773                              <1> ;	FIXED DISK DATA AREAS		:
  2774                              <1> ;----------------------------------------
  2775                              <1> 
  2776 000068BB ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2777 000068BC ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2778 000068BD ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2779                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2780                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2781                              <1> ;port2_off	resb	1		; Hard disk controller 2 - port offset
  2782                              <1> 
  2783 000068BE ????                <1> alignb 4
  2784                              <1> 
  2785                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2786                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2787                              <1> HF_TBL_VEC: ; 22/12/2014	
  2788 000068C0 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2789 000068C4 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2790 000068C8 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2791 000068CC ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2792                              <1> 
  2793                              <1> ; 03/01/2015
  2794 000068D0 ??                  <1> LBAMode:     	resb	1
  2795                              <1> 
  2796                              <1> ; *****************************************************************************
  2730                                  
  2731                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2732                                  
  2733                                  ;alignb 2
  2734                                  
  2735                                  ; 02/01/2022
  2736                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2737                                  
  2738                                  ; 17/04/2021
  2739                                  ; (memory page swap parameters are disabled as temporary)
  2740                                  ;
  2741                                  ;; Memory (swap) Data (11/03/2015)
  2742                                  ; 09/03/2015
  2743                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2744                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2745                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2746                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2747                                  ;swpd_next:  resd 1 ; next free page block
  2748                                  ;swpd_last:  resd 1 ; last swap page block	
  2749                                  
  2750 000068D1 ??????                  alignb 4
  2751                                  
  2752                                  ; 10/07/2015
  2753                                  ; 28/08/2014
  2754 000068D4 ????????                error_code:  resd 1
  2755                                  ; 29/08/2014
  2756 000068D8 ????????                FaultOffset: resd 1
  2757                                  ; 21/09/2015
  2758 000068DC ????????                PF_Count:    resd 1 ; total page fault count
  2759                                  		    ; (for debugging - page fault analyze)
  2760                                  		    ; 'page _fault_handler' (memory.s)
  2761                                  		    ; 'sysgeterr' (u9.s)
  2762                                  ; 23/02/2022
  2763 000068E0 ????????                rtc_ticks:  resd 1  ; (temporary! this rtc counter value may be used 
  2764                                  		    ;  for a system call in next retro unix 386 version)
  2765                                  		    ; -2 ticks per second-
  2766                                  ;; 21/08/2015
  2767                                  ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s
  2768                                  
  2769                                  ; 02/01/2022
  2770                                  %include 'ux.s'	; 12/04/2015 (unix system/user/process data)
  2771                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2772                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2773                              <1> ; ****************************************************************************
  2774                              <1> ; Retro UNIX 386 v1.2 Kernel (v0.2.2.3) - ux.s 
  2775                              <1> ; Last Modification: 08/06/2022
  2776                              <1> ;
  2777                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2778                              <1> ; (Modified from 
  2779                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2780                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2781                              <1> ; ----------------------------------------------------------------------------
  2782                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2783                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2784                              <1> ; <Bell Laboratories (17/3/1972)>
  2785                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2786                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2787                              <1> ; ****************************************************************************
  2788                              <1> 
  2789                              <1> ; 15/07/2022
  2790                              <1> ; 15/05/2022
  2791                              <1> ; 21/03/2022
  2792                              <1> ; 27/02/2022
  2793                              <1> ; 12/01/2022
  2794                              <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility)
  2795                              <1> ; 18/07/2021
  2796                              <1> ; 15/07/2021
  2797                              <1> ; 12/05/2021
  2798                              <1> ; 09/05/2021
  2799                              <1> ; 06/05/2021
  2800                              <1> ; 02/05/2021
  2801                              <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM)
  2802                              <1> 
  2803                              <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM)
  2804                              <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM)
  2805                              <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock
  2806                              <1> 
  2807                              <1> ; 14/01/2020 - Super Block modification:
  2808                              <1> ;	     - Extended sections/divisions (consequental sectors)
  2809                              <1> ;	     - (for swapping, configuration, boot space etc.)	
  2810                              <1> 
  2811                              <1> ; 26/01/2020 (unix386.s, ux.s)
  2812                              <1> ; 14/01/2020
  2813                              <1> SB.HiddenSects	equ SB.BootSectAddr
  2814                              <1> SB.TotalSects	equ SB.VolumeSize
  2815                              <1> 
  2816                              <1> ; 11/05/2021 (Retro UNIX 386 v2)
  2817                              <1> ; Super block status byte (byte 0 of SB.status dword)
  2818                              <1> ; 	bit 0 - superblock modified flag
  2819                              <1> ; 	bit 1 - inode map modified flag
  2820                              <1> ; 	bit 2 - free blocks map modified flag
  2821                              <1> ; 	bit 3 - inode table modified flag
  2822                              <1> ;; 	bit 4 - boot sector modified flag ; 17/08/2021
  2823                              <1> ; 17/08/2021
  2824                              <1> ;	bit 4 - file data write error (for SB.LastInode)
  2825                              <1> ;	bit 5 - inode table write error (for SB.LastInode)
  2826                              <1> ;	bit 6 - inode map write error (for SB.LastInode)
  2827                              <1> ;	bit 7 - free blocks map write error (for SB.LastInode)
  2828                              <1> 	
  2829                              <1> ; 21/12/2019
  2830                              <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 
  2831                              <1> ;	       (UNIXHDFS.ASM)
  2832                              <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1)
  2833                              <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0)
  2834                              <1> 
  2835                              <1> bsFSystemID 	equ 2  ; db 'RUFS'	
  2836                              <1> bsVolumeSerial 	equ 6  ; dd 0 ; (4 bytes)
  2837                              <1> bsFDSign	equ 10 ; db 'fd'
  2838                              <1> bsDriveNumber 	equ 12 ; db 0 ; fd0 or fd1 (0 or 1)
  2839                              <1> bsReserved 	equ 13 ; db 0 ; (512 bytes per sector)	
  2840                              <1> bsSecPerTrack	equ 14 ; db 18 ; (9 or 15)	
  2841                              <1> bsHeads		equ 15 ; db  ; 2
  2842                              <1> bsTracks	equ 16 ; dw 80 ; bsCylinders
  2843                              <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number
  2844                              <1> bsInfoEndsign	equ 20 ; db '@'
  2845                              <1> ; 21/12/2019
  2846                              <1> bsMagic		equ 20 ; db '@'
  2847                              <1> bsPartitionID	equ 21 ; db 0 ; db 71h
  2848                              <1> bsHiddenSects	equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA)
  2849                              <1> 
  2850                              <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags
  2851                              <1> ; ------------------------------------------------------------------
  2852                              <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020
  2853                              <1> ; ------------------------------------------------------------------
  2854                              <1> 
  2855                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  2856                              <1> ; 1000000000000000b 	IFREG - 1 = regular file (8000h)
  2857                              <1> ; 0100000000000000b	IFDIR - 1 = directory (4000h)
  2858                              <1> ; 0010000000000000b	IRSVD - 0 = reserved bit (2000h) ; Mounted flag
  2859                              <1> ; 0001000000000000b	ILARG - large file addressing bit (1000h)
  2860                              <1> ; 0000100000000000b	ISUID - set user id on exec (800h)
  2861                              <1> ; 0000010000000000b	ISGID - set group id on exec (400h)
  2862                              <1> ; 0000001000000000b	IEXTT - 1 = use extents (200h)
  2863                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2864                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2865                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2866                              <1> ; 0000000000100000b	read, group (20h)
  2867                              <1> ; 0000000000010000b	write, group (10h)
  2868                              <1> ; 0000000000001000b	execute, group (08h)
  2869                              <1> ; 0000000000000100b	read, others (04h)
  2870                              <1> ; 0000000000000010b	write, others (02h)
  2871                              <1> ; 0000000000000001b	execute, others (01h)
  2872                              <1> 
  2873                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  2874                              <1> ; 1000000000000000b 	IFREG - 0 = device file (8000h)
  2875                              <1> ; 0100000000000000b	IFBLK - 1 = block device (4000h)
  2876                              <1> ; 0010000000000000b	IFCHR - character special (2000h) -always 1-
  2877                              <1> ; 0001000000000000b	IFIFO - fifo special (1000h)
  2878                              <1> ; 0000100000000000b	IPIPE - pipe special (800h) ; 07/02/2020
  2879                              <1> ; 0000010000000000b	IREDIR - redirected (400h)  ; 07/02/2020
  2880                              <1> ; 0000001000000000b	IEXTR - 1 = external device driver (200h)
  2881                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2882                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2883                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2884                              <1> ; 0000000000100000b	read, group (20h)
  2885                              <1> ; 0000000000010000b	write, group (10h)
  2886                              <1> ; 0000000000001000b	execute, group (08h)
  2887                              <1> ; 0000000000000100b	read, others (04h)
  2888                              <1> ; 0000000000000010b	write, others (02h)
  2889                              <1> ; 0000000000000001b	execute, others (01h)
  2890                              <1> 
  2891                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2892                              <1> ; (SB structure has been moved from here to 'sysdefs.s'
  2893                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2894                              <1> ; (('ux.s' bss section addresses are being overlapped
  2895                              <1> ;    when SB structure is defined in 'ux.s'))
  2896                              <1> 
  2897                              <1> %if 0
  2898                              <1> 
  2899                              <1> struc SB ; SuperBlock
  2900                              <1> 
  2901                              <1> .Header:	resd 1
  2902                              <1> ;.HiddenSects:
  2903                              <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2904                              <1> ;.TotalSects:
  2905                              <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)
  2906                              <1> .Version:	resd 1	
  2907                              <1> .BlockSize:	resd 1	
  2908                              <1> .InodeCount:	resd 1	
  2909                              <1> .FreeMapAddr:	resd 1	
  2910                              <1> .FreeMapSize:	resd 1	
  2911                              <1> .InodeMapAddr:	resd 1	
  2912                              <1> .InodeMapSize:	resd 1	
  2913                              <1> .InodeTblAddr:	resd 1	
  2914                              <1> .InodeTblSize:	resd 1	
  2915                              <1> .FreeInodes:	resd 1	
  2916                              <1> .FirstFreeIno:	resd 1	
  2917                              <1> .FreeBlocks:	resd 1	
  2918                              <1> .FirstFreeBlk:	resd 1	
  2919                              <1> .BootSecParms:	resb 19	; v1
  2920                              <1> .BSExtension:	resb 5	; v2 HDFS
  2921                              <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2922                              <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2923                              <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2924                              <1> .ModifTime:	resd 1	; (last) modification time (*)
  2925                              <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2926                              <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2927                              <1> .LBA_rw:	resb 1
  2928                              <1> .ClusterSize:	resb 1
  2929                              <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2930                              <1> .Mounted:	resb 1
  2931                              <1> .MountInode:	resd 1  ; double word
  2932                              <1> .DevMajor:	resb 1
  2933                              <1> .DevMinor:	resb 1
  2934                              <1> .LongName:	resb 1
  2935                              <1> .Direntry32:	resb 1
  2936                              <1> ; 18/07/2021
  2937                              <1> .FileBuffer:	resd 1
  2938                              <1> .ItabBuffer:	resd 1
  2939                              <1> .ImapBuffer:	resd 1
  2940                              <1> .FmapBuffer:	resd 1
  2941                              <1>  ; 15/07/2021
  2942                              <1> .LastInode:	resd 1
  2943                              <1> ; 02/05/2021
  2944                              <1> .FmapIndex:	resd 1
  2945                              <1> .ImapIndex:	resd 1
  2946                              <1> .ItableIndex:	resd 1
  2947                              <1> .Reserved:	resb 508-148 ; 18/07/2021
  2948                              <1> .Footer:	resd 1
  2949                              <1> 
  2950                              <1> endstruc
  2951                              <1> 
  2952                              <1> %endif
  2953                              <1> 
  2954                              <1> alignb 2
  2955                              <1> 
  2956                              <1> inode:
  2957                              <1> 	;; 11/03/2013. 
  2958                              <1> 	;;Derived from UNIX v1 source code 'inode' structure (ux).
  2959                              <1> 	;;i.
  2960                              <1> 	;
  2961                              <1> 	;i.flgs: resw 1
  2962                              <1> 	;i.nlks: resb 1
  2963                              <1> 	;i.uid:	 resb 1
  2964                              <1>         ;i.size: resw 1 ; size
  2965                              <1> 	;i.dskp: resw 8 ; 16 bytes
  2966                              <1> 	;i.ctim: resd 1
  2967                              <1> 	;i.mtim: resd 1
  2968                              <1> 	;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1)
  2969                              <1> 
  2970                              <1> 	; 26/01/2020
  2971                              <1> 	; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model
  2972                              <1> 	;	(15/09/2029 .. 18/12/2019)
  2973                              <1> 
  2974 000068E4 ????                <1> 	i.flgs:   resw 1	; /* mode and type of file */
  2975 000068E6 ????                <1> 	i.nlks:	  resw 1	; /* number of links to file */
  2976 000068E8 ????                <1> 	i.uid:	  resw 1	; /* owner's user id */  - 0 to 655535 -
  2977 000068EA ??                  <1> 	i.gid:	  resb 1	; /* owner's group id */ - o to 255 -
  2978 000068EB ??                  <1> 	i.size_h: resb 1	; /* number of bytes in file */ ; byte 5
  2979 000068EC ????????            <1> 	i.size:	  resd 1 ; size	; /* number of bytes in file */
  2980 000068F0 <res 28h>           <1> 	i.dskp:	  resd 10 ; 40 bytes ; /* disk block addresses */
  2981 00006918 ????????            <1> 	i.atim:	  resd 1	; /* time last accessed */
  2982 0000691C ????????            <1> 	i.mtim:	  resd 1	; /* time last modified */
  2983 00006920 ????????            <1> 	i.ctim:	  resd 1	; /* time created */
  2984                              <1> 
  2985                              <1> I_SIZE	equ $ - inode
  2986                              <1> 
  2987                              <1> process:
  2988                              <1> 	; 27/02/2022
  2989                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2) 
  2990                              <1> 	; 06/05/2015
  2991                              <1> 	; 11/03/2013 - 05/02/2014
  2992                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2993                              <1> 	;p.
  2994                              <1> 	
  2995 00006924 <res 20h>           <1>         p.pid:   resw nproc
  2996 00006944 <res 20h>           <1>         p.ppid:  resw nproc
  2997                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2998 00006964 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2999                              <1> 	; 27/02/2022 (p.waitc is not used)
  3000                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  3001 00006974 <res 10h>           <1> 	p.link:	 resb nproc
  3002 00006984 <res 10h>           <1> 	p.stat:	 resb nproc
  3003                              <1> 
  3004                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 feature only !) 
  3005 00006994 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  3006                              <1> 			    ; 'user' structure	
  3007                              <1> 
  3008                              <1> P_SIZE	equ $ - process
  3009                              <1> 
  3010                              <1> ; fsp table (original UNIX v1)
  3011                              <1> ;
  3012                              <1> ;Entry
  3013                              <1> ;          15                                      0
  3014                              <1> ;  1     |---|---------------------------------------|
  3015                              <1> ;        |r/w|       i-number of open file           |
  3016                              <1> ;        |---|---------------------------------------| 
  3017                              <1> ;        |               device number               |
  3018                              <1> ;        |-------------------------------------------|
  3019                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  3020                              <1> ;        |-------------------------------------------| 
  3021                              <1> ;        |  flag that says    | number of processes  |
  3022                              <1> ;        |   file deleted     | that have file open  |
  3023                              <1> ;        |-------------------------------------------| 
  3024                              <1> ;  2     |                                           |
  3025                              <1> ;        |-------------------------------------------| 
  3026                              <1> ;        |                                           |
  3027                              <1> ;        |-------------------------------------------|
  3028                              <1> ;        |                                           |
  3029                              <1> ;        |-------------------------------------------|
  3030                              <1> ;        |                                           |
  3031                              <1> ;        |-------------------------------------------| 
  3032                              <1> ;  3     |                                           | 
  3033                              <1> ;        |                                           |  
  3034                              <1> ;
  3035                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  3036                              <1> 
  3037                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3038                              <1> 
  3039                              <1> ;Entry
  3040                              <1> ;         15                    7                   0
  3041                              <1> ;  1     |-------------------------------------------|
  3042                              <1> ;        |   	     i-number of open file           |
  3043                              <1> ;        |-------------------------------------------| 
  3044                              <1> ;        |        high word of 32 bit i-number       |
  3045                              <1> ;        |-------------------------------------------|
  3046                              <1> ;        | open mode & status  |   device number     |
  3047                              <1> ;        |-------------------------------------------|
  3048                              <1> ;        |    reserved byte    |     open count      |
  3049                              <1> ;        |-------------------------------------------| 
  3050                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3051                              <1> ;        |-------------------------------------------|
  3052                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3053                              <1> ;        |-------------------------------------------|
  3054                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3055                              <1> ;        |-------------------------------------------|
  3056                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3057                              <1> ;        |-------------------------------------------|
  3058                              <1> ;  2     |                                           |
  3059                              <1> ;        |-------------------------------------------| 
  3060                              <1> ;        |                                           |
  3061                              <1> ;        |-------------------------------------------|
  3062                              <1> ;        |                                           |
  3063                              <1> ;        |-------------------------------------------|
  3064                              <1> ;        |                                           |
  3065                              <1> ;        |-------------------------------------------| 
  3066                              <1> ;        |                                           | 
  3067                              <1> 
  3068                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3069                              <1> ; (file structure has been moved from here to 'sysdefs.s'
  3070                              <1> ;	to overcome NASM's bss addressing bug !!!)
  3071                              <1> ; (('ux.s' bss section addresses are being overlapped
  3072                              <1> ;    when file file structure is defined in 'ux.s'))
  3073                              <1> 
  3074                              <1> %if 0
  3075                              <1> 
  3076                              <1> ; 22/11/2021
  3077                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  3078                              <1> 
  3079                              <1> struc file	; open files (fsp) structure
  3080                              <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  3081                              <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  3082                              <1>   .drive:  resb 1  ; logical drive (disk) number
  3083                              <1>   .flags:  resb 1  ; open mode and status
  3084                              <1>   .count:  resb 1  ; number of processes that have file open
  3085                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  3086                              <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  3087                              <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  3088                              <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  3089                              <1>  .size:  ; = 16		
  3090                              <1> endstruc
  3091                              <1> 
  3092                              <1> %endif
  3093                              <1> 
  3094                              <1> ; 01/01/2022
  3095                              <1> ; 22/11/2021
  3096                              <1> ;fp.size equ file.size
  3097                              <1> 
  3098                              <1> ; 02/01/2022
  3099 000069D4 <res 320h>          <1> fsp:	resb nfiles*16 ; (NFILES*fp.size)
  3100                              <1> ; 01/01/2022
  3101                              <1> ; 22/11/2021 (16/05/2021)
  3102                              <1> ;fsp:	resb NFILES*16 ; (NFILES*fp.size)
  3103                              <1> ; 15/04/2015
  3104                              <1> ;fsp:	resb nfiles*10 ; 11/05/2015 (8 -> 10)
  3105                              <1> 
  3106 00006CF4 <res 48h>           <1> bufp:	resd (nbuf+2) ; will be initialized 
  3107 00006D3C ????????            <1> ii:	resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0)
  3108                              <1> ; 22/11/2021
  3109 00006D40 ??                  <1> idev:	resb 1 ; logical drive number of current inode, [ii]
  3110 00006D41 ??                  <1> cdev:	resb 1 ; current logical drive number for current user
  3111                              <1> 
  3112                              <1> ; 18/05/2015
  3113                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  3114                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  3115                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  3116                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  3117                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  3118                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  3119                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  3120                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  3121                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  3122                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  3123                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  3124 00006D42 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  3125                              <1> 	        ; as above, for physical drives numbers in following table
  3126 00006D43 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  3127                              <1> ; 15/04/2015
  3128                              <1> ;active: resb 1 ; 15/07/2022
  3129                              <1> ;	 resb 1 ; 09/06/2015
  3130 00006D44 ????                <1> mpid:	 resw 1
  3131                              <1> ; 22/11/2021 (32 bit inode numbers)
  3132 00006D46 ????????            <1> rootdir: resd 1
  3133 00006D4A ????????            <1> mnti:	 resd 1
  3134                              <1> ; 15/05/2022 ; (parent dir inumber of [mnti])
  3135 00006D4E ????????            <1> mntp:	 resd 1 
  3136                              <1> 
  3137                              <1> ; 14/02/2014
  3138                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  3139                              <1> ;		      Single level run queue
  3140                              <1> ;		      (in order to solve sleep/wakeup lock)
  3141 00006D52 ????                <1> runq:	resw 1
  3142 00006D54 ??                  <1> imod:	resb 1
  3143 00006D55 ??                  <1> imodx:	resb 1 ; 09/01/2022 - Retro UNIX 386 v1.2
  3144 00006D56 ??                  <1> smod:	resb 1
  3145 00006D57 ??                  <1> mmod:	resb 1
  3146                              <1> ;	resb 1 ; 09/01/2022 
  3147 00006D58 ??                  <1> sysflg:	resb 1
  3148                              <1> 
  3149 00006D59 ??????              <1> alignb 4
  3150                              <1> 
  3151                              <1> user:
  3152                              <1> 	; 01/01/2022
  3153                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3154                              <1> 	; 24/10/2021
  3155                              <1> 	; 18/10/2021
  3156                              <1> 	; 10/06/2021
  3157                              <1> 	; 30/05/2021
  3158                              <1> 	; 29/05/2021
  3159                              <1> 	; 21/05/2021
  3160                              <1> 	; 20/05/2021
  3161                              <1> 	; 16/05/2021
  3162                              <1> 	; 01/05/2021
  3163                              <1> 	; 27/03/2021
  3164                              <1> 	; 17/04/2020, 28/04/2020
  3165                              <1> 	; 25/03/2020, 28/03/2020
  3166                              <1> 	; 20/03/2020, 22/03/2020, 23/03/2020
  3167                              <1> 	; 05/03/2020, 08/03/2020, 14/03/2020
  3168                              <1> 	; 07/02/2020 - Retro UNIX 386 v2
  3169                              <1> 	;
  3170                              <1> 	; 27/02/2017 - TRDOS 386
  3171                              <1> 	; 13/01/2017 - TRDOS 386
  3172                              <1> 	; 10/01/2017 - TRDOS 386
  3173                              <1> 	; 19/12/2016 - TRDOS 386	
  3174                              <1> 	; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 
  3175                              <1> 	; 	       [u.pri] usage method modification
  3176                              <1> 	;
  3177                              <1> 	; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names)
  3178                              <1> 	; 18/10/2015
  3179                              <1> 	; 12/10/2015
  3180                              <1> 	; 21/09/2015
  3181                              <1> 	; 24/07/2015
  3182                              <1> 	; 16/06/2015
  3183                              <1> 	; 09/06/2015
  3184                              <1> 	; 11/05/2015
  3185                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  3186                              <1> 	; 10/10/2013
  3187                              <1> 	; 11/03/2013. 
  3188                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  3189                              <1> 	;u.
  3190                              <1> 
  3191 00006D5C ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  3192 00006D60 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  3193 00006D64 ????????            <1> 	u.r0:	  resd 1 ; eax
  3194 00006D68 ????                <1> 	u.cdir:	  resw 1
  3195 00006D6A ????                <1> 		  resw 1 ; 28/03/2020 - reserved for 32 bit inode number
  3196                              <1> 	;u.cdrv:  resw 1 ; 17/04/2020 (dword alignment) 
  3197 00006D6C ??                  <1> 	u.cdrv:   resb 1 ; 01/05/2021
  3198 00006D6D ??                  <1> 		  resb 1 ; 01/05/2021 (dword alignment)
  3199 00006D6E <res Ah>            <1> 	u.fp:	  resb 10 ; Retro UNIX 386 v1
  3200                              <1> 	;u.fp:	  resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 
  3201                              <1> 	u.fsp:	  ; 16/05/2021
  3202 00006D78 ????????            <1> 	u.fofp:	  resd 1 ; 16/05/2021 (pointer to fsp entry)
  3203 00006D7C ????????            <1> 	u.dirp:	  resd 1
  3204 00006D80 ????????            <1> 	u.namep:  resd 1
  3205 00006D84 ????????            <1> 	u.off:	  resd 1
  3206                              <1> 	;	  resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr
  3207 00006D88 ????????            <1> 	u.base:	  resd 1
  3208 00006D8C ????????            <1> 	u.count:  resd 1
  3209 00006D90 ????????            <1> 	u.nread:  resd 1
  3210 00006D94 ????????            <1> 	u.break:  resd 1 ; break
  3211                              <1> 	; 16/05/2021 (Retro UNIX 386 v2)
  3212 00006D98 ??                  <1> 	u.mode:   resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode)
  3213                              <1> 	; 10/01/2017 (TRDOS 386, relocation and dword alignment)
  3214                              <1> 	; tty number (rtty, rcvt, wtty)
  3215 00006D99 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  3216 00006D9A ????                <1> 	u.ttyp:	  resw 1 
  3217 00006D9C <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  3218                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  3219 00006DAC ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  3220 00006DAD ??                  <1> 		  resb 1 ; 17/04/2020
  3221 00006DAE ??                  <1> 	u.pri:	  resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2)
  3222 00006DAF ??                  <1> 		  resb 1 ; 17/04/2020
  3223                              <1> 	; 10/06/2021
  3224                              <1> 	;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2
  3225                              <1> 	;	  resw 1 ; reserved ; 21/05/2021	
  3226 00006DB0 ????                <1> 	u.intr:	  resw 1
  3227 00006DB2 ????                <1> 	u.quit:	  resw 1
  3228                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  3229                              <1> 	;u.ilgins: resw 1 ; 10/01/2017
  3230                              <1> 	;u.cdrv:  resw 1 ; cdev ; 17/04/2020 (moved to up)
  3231                              <1> 	;u.uid:	  resb 1 ; uid
  3232                              <1> 	;u.ruid:  resb 1
  3233 00006DB4 ??                  <1> 	u.bsys:	  resb 1
  3234 00006DB5 ??                  <1> 	u.uno:	  resb 1
  3235 00006DB6 ????                <1>         u.uid:	  resw 1 ; uid	; 27/03/2021 - Retro UNIX 386 v2
  3236 00006DB8 ????                <1> 	u.ruid:	  resw 1	; 16 bit uid
  3237 00006DBA ??                  <1> 	u.gid:	  resb 1 ; gid 	; 27/03/2021 - Retro UNIX 386 v2
  3238 00006DBB ??                  <1> 	u.rgid:	  resb 1
  3239                              <1> 	; 20/05/2021 - Retro UNIX 386 v2
  3240 00006DBC ????????            <1> 	u.procp:  resd 1 ; /* pointer to proc structure */		
  3241 00006DC0 ????????            <1> 	u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  3242 00006DC4 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  3243 00006DC8 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  3244 00006DCC ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  3245                              <1> 		; 24/10/2021 (32 bit value for Retro UNIX 386 v2)
  3246 00006DD0 ????????            <1> 	u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page)
  3247                              <1> 	;u.pncount: resw 1 
  3248                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  3249                              <1> 	;u.pnbase:  resd 1 
  3250                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  3251 00006DD4 ????                <1> 	u.rsvd:	  resw 1 ; 04/12/2021 (dword alignment)
  3252                              <1> 			 ; 09/06/2015
  3253 00006DD6 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign
  3254                              <1> 		; 08/03/2020 (block device read/write flag for 'sioreg')		
  3255 00006DD7 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  3256                              <1> 			 ; 24/07/2015 - 24/06/2015
  3257                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  3258                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  3259                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  3260                              <1>  			 ; 24/06/2015	  	
  3261                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  3262                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  3263                              <1> 	; last error number
  3264 00006DD8 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  3265                              <1> 			; Retro UNIX 8086/386 v1 feature only!
  3266                              <1> 			; 21/09/2015 (debugging - page fault analyze)
  3267 00006DDC ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  3268                              <1> 		; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig)
  3269                              <1> ;	u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits	
  3270                              <1> ;	u.srb:	  resb 1 ; signal handling/responding method
  3271                              <1> ;	u.snum:	  resb 1 ; signal number (last signal number)
  3272                              <1> ;	u.exit:	  resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2
  3273                              <1> ;	u.s_lock: resb 1 ; signal handling (phase) lock	
  3274                              <1> ;	u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address
  3275                              <1> ;	u.s_time: resd 1 ; signal time in unix epoch format		
  3276                              <1> 		; 19/12/2016 (TRDOS 386)	
  3277                              <1> ;	u.tcb:	  resd 1 ; Timer callback address/flag which will be used by timer int
  3278                              <1> 		; 13/01/2017 (TRDOS 386)
  3279                              <1> ;	u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele')
  3280                              <1> ;	u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user)
  3281                              <1> 		; 26/02/2017 (TRDOS 386)
  3282                              <1> ;	u.irqc:	  resb 1  ; Count of IRQ callback services (IRQs in use)
  3283                              <1> 		; 28/02/2017 (TRDOS 386) 
  3284                              <1> ;	u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0)
  3285                              <1> ;	u.r_lock:  resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock)
  3286                              <1> ;	u.r_mode:  resb 1 ; running mode during hardware interrupt
  3287                              <1> 		; 07/02/2020 - Retro UNIX 386 v2
  3288                              <1> ;	u.redir:  resb 1 ; device func redirection permitted by user (if u.redir > 0)
  3289                              <1> 		; 26/02/2020 - Retro UNIX 386 v2
  3290                              <1> ;	u.rwm:	  resb 1  ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 
  3291                              <1> 		; 24/02/2020 - Retro UNIX 386 v2
  3292                              <1> 		; 24/10/2021 (32 bit value)
  3293                              <1> ;	u.scount: resd 1 ; sub byte count ; 22/03/2020 
  3294                              <1> 		; 07/03/2020 - Retro UNIX 386 v2
  3295                              <1> ;	u.bps:	  resw 1 ; u.bps = bytes per sector, for readi and writei
  3296                              <1> ;		  resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers)	
  3297                              <1> 		; 23/03/2020 - Retro UNIX 386 v2
  3298                              <1> ;	u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'-
  3299                              <1> 		; 28/04/2020 - Retro UNIX 386 v2
  3300                              <1> ;	u.lock:	  resb 1 ; Device lock flag (bit 0 is for device/disk read/write)
  3301                              <1> 		; 24/04/2020
  3302                              <1> 		; 17/04/2020 - Retro UNIX 386 v2
  3303                              <1> ;	u.ifs:	  resb 1 ; (current) installable file system driver index number
  3304                              <1> 		; 25/03/2020
  3305                              <1> 		; 20/03/2020
  3306                              <1> 	;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count)	
  3307                              <1> 
  3308                              <1> 		; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi')
  3309                              <1> 	;u.limit: resd 1  ; disk/file size limit for block device read/write ('sioreg')			
  3310                              <1> 	;	  resd 1  ; 08/03/2020 - 64 bit limit (disk size in bytes)
  3311                              <1> 	;	; 26/02/2020 - Retro UNIX 386 v2
  3312                              <1> 	;u.sector: resd 1  ; current sector (for readi and writei, device r/w)  		
  3313                              <1> 	;u.buffer: resd 1  ; current buffer (for readi and writei, device r/w) 
  3314                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3315                              <1> 	;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers
  3316                              <1> 	;u.zero:  resw 1 ; 14/03/2020 - Must be ZERO for current version
  3317                              <1> 		; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3318                              <1> ;	u.device: resd 1 ; (blk, chr) device description table (entry) address 	
  3319                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3320                              <1> ;	u.function: resd 1 ; device function (read, write)
  3321                              <1> 		; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei)
  3322                              <1> ;	u.buffer: resd 1  ; for saving buffer header address for 'poke'
  3323                              <1> ;	u.inode:  resw 1  ; for saving inode number of current (device) inode
  3324                              <1> ;		  resw 1  ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number			
  3325                              <1> ;	u.idev:	  resb 1  ; for saving logical drv number of current (dev) inode
  3326                              <1> 		; 04/12/2021
  3327                              <1> ;	u.rsvd2:  resw 1  ; (for dword alignment)	
  3328                              <1> 		; 27/02/2017 (TRDOS 386) 
  3329                              <1> ;; 31/12/2021 - temporary !
  3330                              <1> ;	u.fpsave: resb 1  ; TRDOS 386, 'save/restore FPU registers' flag
  3331                              <1> alignb 4
  3332                              <1> 	; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 
  3333                              <1> 	;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers
  3334                              <1> 	; 30/05/2021 - Retro UNIX 386 v2
  3335                              <1> ;	u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers	
  3336                              <1> alignb 4
  3337                              <1> 
  3338                              <1> U_SIZE	equ $ - user
  3339                              <1> 
  3340                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3341 00006DE0 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3342 00006DE4 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3343 00006DE8 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3344                              <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec'
  3345                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount')
  3346 00006DEC ????????            <1> ncount: resd 1	; remain byte count in page for 'namei' & 'sysexec'
  3347                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3348                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc')
  3349 00006DF0 ????????            <1> argc:	resd 1	; argument count for 'sysexec'
  3350 00006DF4 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3351                              <1> 
  3352                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3353                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3354 00006DF8 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3355 00006DF9 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3356 00006DFA ??                  <1> mget_rw: resb 1 ; 22/11/2021 
  3357 00006DFB ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3358                              <1> 
  3359                              <1> ; 08/06/2022 - (BugFix) ! (level: resd 0) !
  3360                              <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility
  3361 00006DFC ????????            <1> level:	resd 1  ; level, level+1, level+2, level+3  ; for 'mget' procedure
  3362                              <1> 
  3363                              <1> ; (02/01/2022)
  3364                              <1> ; 27/11/2021
  3365                              <1> ; these are will be used for disk block allocation ('alloc' proc)
  3366                              <1> free_map_offset: 
  3367 00006E00 ????????            <1> 		resd 1
  3368 00006E04 ????????            <1> free_map_index:	resd 1
  3369                              <1> free_map_sector:
  3370 00006E08 ????????            <1> 		resd 1
  3371                              <1> ;free_map_buffer:
  3372                              <1> ;		resd 1
  3373                              <1> 
  3374                              <1> ; 12/01/2022
  3375                              <1> ; 27/11/2021 - temporary !
  3376                              <1> ;s.time:	resd 1
  3377                              <1> 
  3378                              <1> ;alignb 4
  3379                              <1> 
  3380                              <1> ; (02/01/2022)
  3381                              <1> ; 22/08/2015
  3382                              <1> ;buffer: resb nbuf * 520
  3383                              <1> 
  3384 00006E0C ????????????????    <1> sb0:	resd 2
  3385                              <1> ;s:
  3386                              <1> ; (root disk) super block buffer
  3387                              <1> systm:
  3388                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatible super block
  3389                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3390                              <1> 	; 11/03/2013. 
  3391                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3392                              <1> 	;s.
  3393                              <1> 
  3394                              <1> 	;resw 1
  3395                              <1> 	;resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3396                              <1> 	;resw 1
  3397                              <1> 	;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64
  3398                              <1> 	;s.time: resd 1
  3399                              <1> 	;s.syst: resd 1
  3400                              <1>         ;s.wait_: resd 1 ; wait
  3401                              <1> 	;s.idlet: resd 1
  3402                              <1> 	;s.chrgt: resd 1
  3403                              <1> 	;s.drerr: resw 1
  3404                              <1> 
  3405                              <1> 	; 27/11/2021
  3406 00006E14 <res 200h>          <1> 	resb 512	
  3407                              <1> 
  3408                              <1> ;S_SIZE	equ $ - systm
  3409                              <1> 
  3410                              <1> 	;resb 512-S_SIZE ; 03/06/2015
  3411                              <1> 
  3412 00007014 ????????????????    <1> sb1:	resd 2
  3413                              <1> ; (mounted disk) super block buffer
  3414                              <1> mount:	
  3415 0000701C <res 200h>          <1> 	resb 512  ; 03/06/2015
  3416                              <1> 
  3417                              <1> ; 21/03/2022
  3418                              <1> ; hard disk masterboot sector buffer
  3419 0000721C ????????????????    <1> mbrbuf: resd 2
  3420 00007224 <res 200h>          <1> 	resb 512
  3421                              <1> 
  3422                              <1> ; 10/01/2022
  3423 00007424 <res 200h>          <1> dbli_buf: resb 512  ; double indir ptr buff for 'itrunc', 'tloop'
  3424 00007624 <res 200h>          <1> trpi_buf: resb 512  ; triple indir ptr buff for 'itrunc', 'tloop'
  3425                              <1> 
  3426                              <1> ;/ ux -- unix
  3427                              <1> ;
  3428                              <1> ;systm:
  3429                              <1> ;
  3430                              <1> ;	.=.+2
  3431                              <1> ;	.=.+128.
  3432                              <1> ;	.=.+2
  3433                              <1> ;	.=.+64.
  3434                              <1> ;	s.time: .=.+4
  3435                              <1> ;	s.syst: .=.+4
  3436                              <1> ;	s.wait: .=.+4
  3437                              <1> ;	s.idlet:.=.+4
  3438                              <1> ;	s.chrgt:.=.+4
  3439                              <1> ;	s.drerr:.=.+2
  3440                              <1> ;inode:
  3441                              <1> ;	i.flgs: .=.+2
  3442                              <1> ;	i.nlks: .=.+1
  3443                              <1> ;	i.uid:  .=.+1
  3444                              <1> ;	i.size: .=.+2
  3445                              <1> ;	i.dskp: .=.+16.
  3446                              <1> ;	i.ctim: .=.+4
  3447                              <1> ;	i.mtim: .=.+4
  3448                              <1> ;	. = inode+32.
  3449                              <1> ;mount:	.=.+1024.
  3450                              <1> ;proc:
  3451                              <1> ;	p.pid:  .=.+[2*nproc]
  3452                              <1> ;	p.dska: .=.+[2*nproc]
  3453                              <1> ;	p.ppid: .=.+[2*nproc]
  3454                              <1> ;	p.break:.=.+[2*nproc]
  3455                              <1> ;	p.link: .=.+nproc
  3456                              <1> ;	p.stat: .=.+nproc
  3457                              <1> ;tty:
  3458                              <1> ;	. = .+[ntty*8.]
  3459                              <1> ;fsp:	.=.+[nfiles*8.]
  3460                              <1> ;bufp:	.=.+[nbuf*2]+6
  3461                              <1> ;sb0:	.=.+8
  3462                              <1> ;sb1:	.=.+8
  3463                              <1> ;swp:	.=.+8
  3464                              <1> ;ii:	.=.+2
  3465                              <1> ;idev:	.=.+2
  3466                              <1> ;cdev:	.=.+2
  3467                              <1> ;deverr: .=.+12.
  3468                              <1> ;active: .=.+2
  3469                              <1> ;rfap:	.=.+2
  3470                              <1> ;rkap:	.=.+2
  3471                              <1> ;tcap:	.=.+2
  3472                              <1> ;tcstate:.=.+2
  3473                              <1> ;tcerrc: .=.+2
  3474                              <1> ;mnti:	.=.+2
  3475                              <1> ;mntd:	.=.+2
  3476                              <1> ;mpid:	.=.+2
  3477                              <1> ;clockp: .=.+2
  3478                              <1> ;rootdir:.=.+2
  3479                              <1> ;toutt:	.=.+16.
  3480                              <1> ;touts: .=.+32.
  3481                              <1> ;runq:	.=.+6
  3482                              <1> ;
  3483                              <1> ;wlist:	.=.+40.
  3484                              <1> ;cc:	.=.+30.
  3485                              <1> ;cf:	.=.+31.
  3486                              <1> ;cl:	.=.+31.
  3487                              <1> ;clist:	.=.+510.
  3488                              <1> ;imod:	.=.+1
  3489                              <1> ;smod:	.=.+1
  3490                              <1> ;mmod:	.=.+1
  3491                              <1> ;uquant: .=.+1
  3492                              <1> ;sysflg: .=.+1
  3493                              <1> ;pptiflg:.=.+1
  3494                              <1> ;ttyoch: .=.+1
  3495                              <1> ; .even
  3496                              <1> ; .=.+100.; sstack:
  3497                              <1> ;buffer: .=.+[ntty*140.]
  3498                              <1> ;	.=.+[nbuf*520.]
  3499                              <1> ;
  3500                              <1> ; . = core-64.
  3501                              <1> ;user:
  3502                              <1> ;	u.sp:    .=.+2
  3503                              <1> ;	u.usp:   .=.+2
  3504                              <1> ;	u.r0:    .=.+2
  3505                              <1> ;	u.cdir:  .=.+2
  3506                              <1> ;	u.fp:    .=.+10.
  3507                              <1> ;	u.fofp:  .=.+2
  3508                              <1> ;	u.dirp:  .=.+2
  3509                              <1> ;	u.namep: .=.+2
  3510                              <1> ;	u.off:   .=.+2
  3511                              <1> ;	u.base:  .=.+2
  3512                              <1> ;	u.count: .=.+2
  3513                              <1> ;	u.nread: .=.+2
  3514                              <1> ;	u.break: .=.+2
  3515                              <1> ;	u.ttyp:  .=.+2
  3516                              <1> ;	u.dirbuf:.=.+10.
  3517                              <1> ;	u.pri:   .=.+2
  3518                              <1> ;	u.intr:  .=.+2
  3519                              <1> ;	u.quit:  .=.+2
  3520                              <1> ;	u.emt:   .=.+2
  3521                              <1> ;	u.ilgins:.=.+2
  3522                              <1> ;	u.cdev:  .=.+2
  3523                              <1> ;	u.uid:   .=.+1
  3524                              <1> ;	u.ruid:  .=.+1
  3525                              <1> ;	u.bsys:  .=.+1
  3526                              <1> ;	u.uno:   .=.+1
  3527                              <1> ;. = core
  2771                                  
  2772                                  ; 27/12/2021
  2773 00007824 <res 2080h>             buffer:	resb (nbuf*520)
  2774                                  
  2775                                  bss_end:
  2776                                  
  2777                                  ; 12/12/2021
  2778                                  BSS_SIZE equ bss_end - bss_start
  2779                                  
  2780                                  ; 27/12/2013
  2781                                  _end: ; end of kernel code (and read only data, just before bss)
