     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.6
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.15 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 24/07/2022 (v0.2.1.6) ]
    13                                  ;	 04/02/2016 - Retro UNIX 386 v1.1 (Retro UNIX Kernel v0.2.1.0)	
    14                                  ;	 31/12/2021 - BugFix and Code Optimization (v0.2.1.1)
    15                                  ;	 03/03/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022
    16                                  ;	 04/04/2022 - Inode Table/List Address Modification (v0.2.1.2) -u5.s-
    17                                  ;	 22/04/2022 - BugFix ('mget' -u5.s-)
    18                                  ;	 29/04/2022 - BugFix ('syschmod' -u2.s-) (v0.2.1.2)
    19                                  ;	 ; (v0.2.1.3)
    20                                  ;	 09/05/2022 - u2.s (sysstat), u7.s (sysumount), diskinit.inc  
    21                                  ;	 15/05/2022 - u2.s (namei), u7.s (sysumount)
    22                                  ;	 01/06/2022 - BugFix ('set_date_time' -u0.s-) (v0.2.1.3)
    23                                  ;	 ; (v0.2.1.4)
    24                                  ;	 13/06/2022 - LPT1 (/dev/lpr) printing modification (v0.2.1.4)
    25                                  ;	 14/06/2022 - BugFix (video.inc,'set_cpos' <- u9.s 'putc' carry flg)
    26                                  ;	 ; (v0.2.1.5)
    27                                  ;	 08/07/2022 - diskio.s (diskio simplified by removing the unused code) 
    28                                  ;	 ; (v0.2.1.6) 
    29                                  ;	 15/07/2022 - Simplified and Improved Buffer Handling -u8.s-
    30                                  ;	 16/07/2022 - Code Optimization
    31                                  ;	 17/07/2022 - Code Optimization
    32                                  ;	 18/07/2022 - Code Optimization
    33                                  ;	 19/07/2022 - BugFix (File Offset after disk write error, u6.s, u8.s)
    34                                  ;	 24/07/2022 - keyboard.s (simplified & optimized 'getc_int')	
    35                                  ;
    36                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    37                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    38                                  ; <Bell Laboratories (17/3/1972)>
    39                                  ; <Preliminary Release of UNIX Implementation Document>
    40                                  ;
    41                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    42                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    43                                  ;
    44                                  ; ****************************************************************************
    45                                  ; 31/12/2021 - 15/07/2022
    46                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    47                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    48                                  
    49                                  ; 02/01/2022 - Code Optimization
    50                                  ; Runix Kernel v0.2.1.2
    51                                  ; 24/12/2021 - BugFix and Code Optimization
    52                                  ; Runix Kernel v0.2.1.1 
    53                                  
    54                                  ; 24/12/2013
    55                                  
    56                                  ; Entering protected mode:
    57                                  ; Derived from 'simple_asm.txt' source code file and 
    58                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    59                                  ; (gregor.brunmar@home.se)
    60                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    61                                  ;
    62                                  
    63                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    64                                  ; by Michael Chourdakis (2009) 
    65                                  ; http://www.codeproject.com/Articles/45788/
    66                                  ; http://www.michaelchourdakis.com
    67                                  ;
    68                                  
    69                                  ; Global Descriptor Table:
    70                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    71                                  ; by Linus Torvalds (1991-1992)
    72                                  ;
    73                                  
    74                                  KLOAD	equ 10000h ; Kernel loading address
    75                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    76                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    77                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    78                                  ; 19/03/2015
    79                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    80                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    81                                  ; 24/03/2015
    82                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    83                                  ; 19/03/2015
    84                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    85                                  		     ; (at the end of the 1st 4MB)
    86                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    87                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    88                                  
    89                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    90                                  ;; 27/12/2013
    91                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    92                                  
    93                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    94                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    95                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    96                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    97                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    98                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    99                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
   100                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
   101                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
   102                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
   103                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
   104                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
   105                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
   106                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
   107                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
   108                                  ;----------------------------------------
   109                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
   110                                  ;-----------------------------------------------------------------------------
   111                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
   112                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
   113                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
   114                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
   115                                  
   116                                  ; Memory Allocation Table Address
   117                                  ; 05/11/2014
   118                                  ; 31/10/2014
   119                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   120                                  					; the 1st 1 MB memory space.
   121                                  					; (This address must be aligned
   122                                  					;  on 128 KB boundary, if it will be
   123                                  					;  changed later.)
   124                                  					; ((lower 17 bits of 32 bit M.A.T.
   125                                  					;   address must be ZERO)).
   126                                  					; ((((Reason: 32 bit allocation 
   127                                  					;     instructions, dword steps)))
   128                                  					; (((byte >> 12 --> page >> 5)))  
   129                                  ;04/11/2014	
   130                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   131                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   132                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   133                                  ;
   134                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   135                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   136                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   137                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   138                                  
   139                                  ; 17/02/2015 (unix386.s)
   140                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   141                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   142                                  ;
   143                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   144                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   145                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   146                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   147                                  
   148                                  
   149                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   150                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   151                                  ;
   152                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   153                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   154                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   155                                  		      ; otherwise it is standard FDPT with physical values 	
   156                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   157                                  		      ; (obsolete for IDE/ATA drives)
   158                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   159                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   160                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   161                                  			; Bit 4 : Reserved. Always 0
   162                                  			; Bit 3 : Set to 1 if more than 8 heads
   163                                  			; Bit 2-0 : Reserved. Alsways 0
   164                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   165                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   166                                  
   167                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   168                                  ; (11 bytes long) will be used by diskette handler/bios
   169                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   170                                  
   171                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   172                                  
   173                                  [ORG 0]
   174                                  
   175                                  KSTART: ; 01/01/2022
   176                                   
   177                                  	; 12/11/2014
   178                                  	; Save boot drive number (that is default root drive)
   179 00000000 8816[485C]              	mov	[boot_drv], dl ; physical drv number
   180                                  
   181                                  	; Determine installed memory
   182                                  	; 31/10/2014
   183                                  	;
   184 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   185 00000007 CD15                    	int	15h	   ; for large configurations
   186 00000009 7308                    	jnc	short chk_ms
   187 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   188 0000000D CD15                    	int	15h
   189                                  	;	   
   190                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   191                                  	;out	70h, al ; select CMOS register
   192                                  	;in	al, 71h ; read data (1 byte)
   193                                  	;mov	cl, al
   194                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   195                                  	;out	70h, al ; select CMOS register
   196                                  	;in	al, 71h ; read data (1 byte)
   197                                  	;mov	ch, al
   198                                   	;      
   199 0000000F 89C1                    	mov	cx, ax
   200 00000011 31D2                    	xor	dx, dx
   201                                  chk_ms:
   202 00000013 890E[B45E]              	mov	[mem_1m_1k], cx
   203 00000017 8916[B85E]              	mov	[mem_16m_64k], dx
   204                                  	; 05/11/2014
   205                                  	;and	dx, dx
   206                                  	;jz	short L2
   207 0000001B 81F90004                        cmp     cx, 1024
   208 0000001F 7351                    	jnb	short L0
   209                                  		 ; insufficient memory_error	
   210                                  		 ; Minimum 2 MB memory is needed... 
   211                                  	; 05/11/2014
   212                                  	; (real mode error printing)
   213 00000021 FB                      	sti
   214 00000022 BE[3600]                	mov	si, msg_out_of_memory
   215 00000025 BB0700                  	mov	bx, 7
   216 00000028 B40E                    	mov	ah, 0Eh	; write tty
   217                                  oom_1:
   218 0000002A AC                      	lodsb
   219 0000002B 08C0                    	or	al, al
   220 0000002D 7404                    	jz	short oom_2
   221 0000002F CD10                    	int	10h
   222 00000031 EBF7                    	jmp	short oom_1
   223                                  oom_2:
   224 00000033 F4                              hlt
   225 00000034 EBFD                    	jmp	short oom_2
   226                                  
   227                                  ; 02/01/2022
   228                                  ; 05/11/2014
   229                                  msg_out_of_memory:
   230 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   231 00000039 496E73756666696369-             db      'Insufficient memory !'
   231 00000042 656E74206D656D6F72-
   231 0000004B 792021             
   232 0000004E 0D0A                    	db	0Dh, 0Ah
   233                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   234 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   234 00000059 324D42206D656D6F72-
   234 00000062 79206973206E656564-
   234 0000006B 65642E29           
   235 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   236                                  
   237                                  L0:
   238                                  %include 'diskinit.inc' ; 07/03/2015
   239                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKINIT.INC
   240                              <1> ; Last Modification: 12/07/2022
   241                              <1> 
   242                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   243                              <1> 
   244                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   245                              <1> 
   246                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   247                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   248                              <1> ;L0:
   249                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   250                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   251 00000072 BA7F00              <1> 	mov	dx, 7Fh
   252                              <1> L1:	
   253 00000075 FEC2                <1> 	inc	dl
   254 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   255                              <1> 			; Phoenix EDD v1.1 - EDD v3
   256 00000079 BBAA55              <1> 	mov	bx, 55AAh
   257 0000007C CD13                <1> 	int 	13h
   258 0000007E 721A                <1> 	jc	short L2
   259                              <1> 
   260 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   261 00000084 7514                <1> 	jne	short L2
   262 00000086 FE06[4B5C]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   263 0000008A 8816[4A5C]          <1>         mov     [last_drv], dl  ; last hard disk number
   264 0000008E BB[CE5B]            <1> 	mov	bx, hd0_type - 80h
   265 00000091 01D3                <1> 	add	bx, dx	 
   266 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   267                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   268                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   269                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   270                              <1>                          ;            (EDD) ready (DPTE ready)
   271                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   272                              <1>                          ;            (EDD-3)
   273                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   274 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   275 00000098 72DB                <1> 	jb	short L1
   276                              <1> L2:
   277                              <1> 	; 23/11/2014
   278                              <1> 	; 19/11/2014
   279 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   280                              <1> 	; 04/02/2016 (esi -> si)
   281 0000009C BE[4C5C]            <1> 	mov	si, fd0_type
   282                              <1> L3:
   283                              <1> 	; 14/01/2015
   284 0000009F 8816[495C]          <1> 	mov	[drv], dl
   285                              <1> 	;
   286 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   287 000000A5 CD13                <1> 	int	13h	
   288 000000A7 7210                <1> 	jc	short L4
   289                              <1> 		; BL = drive type (for floppy drives)
   290                              <1> 		; DL = number of floppy drives
   291                              <1> 		;		
   292                              <1> 		; ES:DI = Address of DPT from BIOS
   293                              <1> 		;
   294 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   295                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   296                              <1> 	; 14/01/2015
   297 000000AB E8BB01              <1> 	call	set_disk_parms
   298                              <1> 	; 10/12/2014
   299 000000AE 81FE[4C5C]          <1> 	cmp	si, fd0_type
   300 000000B2 7705                <1> 	ja	short L4
   301 000000B4 46                  <1> 	inc	si ; fd1_type
   302 000000B5 B201                <1> 	mov	dl, 1
   303 000000B7 EBE6                <1> 	jmp	short L3
   304                              <1> L4:
   305                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   306 000000B9 B27F                <1> 	mov	dl, 7Fh
   307                              <1> 	; 24/12/2014 (Temporary)
   308 000000BB 803E[4B5C]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   309                              <1> 	;ja	L10       ; yes, all fixed disk operations
   310                              <1> 			  ; will be performed according to
   311                              <1> 			  ; present EDD specification
   312                              <1> 	; 02/01/2022
   313 000000C0 7603                <1> 	jna	short L5
   314 000000C2 E99100              <1> 	jmp	L10
   315                              <1> L5:
   316 000000C5 FEC2                <1> 	inc 	dl
   317 000000C7 8816[495C]          <1>         mov     [drv], dl
   318 000000CB 8816[4A5C]          <1>         mov     [last_drv], dl ; 14/01/2015
   319 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   320 000000D1 CD13                <1> 	int	13h	; (conventional function)
   321                              <1> 	;jc	L13	; fixed disk drive not ready
   322                              <1> 	; 02/01/2022
   323 000000D3 7303                <1> 	jnc	short L6
   324 000000D5 E98301              <1> 	jmp	L13
   325                              <1> L6:
   326 000000D8 8816[4B5C]          <1>         mov     [hdc], dl ; number of drives
   327                              <1> 	;; 14/01/2013
   328                              <1> 	;;push	cx
   329 000000DC E88A01              <1> 	call	set_disk_parms
   330                              <1> 	;;pop	cx
   331                              <1> 	;
   332                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   333 000000DF 8A16[495C]          <1>         mov     dl, [drv]
   334 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   335 000000E6 80FA80              <1> 	cmp	dl, 80h
   336 000000E9 7603                <1> 	jna	short L7
   337 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   338                              <1> L7:	
   339 000000EE 31C0                <1> 	xor	ax, ax
   340 000000F0 8ED8                <1> 	mov	ds, ax
   341 000000F2 8B37                <1>         mov     si, [bx]
   342 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   343 000000F7 8ED8                <1> 	mov	ds, ax
   344 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   345                              <1> 	;jne	L12 ; invalid FDPT
   346                              <1> 	; 02/01/2022
   347 000000FC 7403                <1> 	je	short L7_8
   348 000000FE E95601              <1> 	jmp	L12
   349                              <1> L7_8:
   350 00000101 BF0000              <1> 	mov	di, HD0_DPT
   351 00000104 80FA80              <1> 	cmp	dl, 80h
   352 00000107 7603                <1> 	jna	short L8
   353 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   354                              <1> L8:
   355                              <1> 	; 30/12/2014
   356 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   357 0000010F 8EC0                <1> 	mov	es, ax
   358                              <1> 	; 24/12/2014
   359 00000111 B90800              <1> 	mov	cx, 8
   360 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   361 00000116 8CC8                <1> 	mov	ax, cs
   362 00000118 8ED8                <1> 	mov	ds, ax
   363                              <1> 	; 02/02/2015
   364 0000011A 8A0E[495C]          <1>         mov     cl, [drv]
   365 0000011E 88CB                <1> 	mov	bl, cl
   366 00000120 B8F001              <1> 	mov	ax, 1F0h
   367 00000123 80E301              <1> 	and	bl, 1
   368 00000126 7406                <1> 	jz	short L9
   369 00000128 C0E304              <1> 	shl	bl, 4
   370 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   371                              <1> L9:
   372 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   373 0000012F 050602              <1> 	add	ax, 206h
   374 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   375 00000133 88D8                <1> 	mov	al, bl
   376 00000135 04A0                <1> 	add	al, 0A0h
   377 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   378                              <1> 	;
   379 00000138 FE06[495C]          <1> 	inc	byte [drv]
   380 0000013C BB[CE5B]            <1> 	mov	bx, hd0_type - 80h
   381 0000013F 01CB                <1> 	add	bx, cx
   382 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   383 00000144 A0[4B5C]            <1> 	mov	al, [hdc]
   384 00000147 FEC8                <1> 	dec	al
   385                              <1> 	;jz	L13
   386                              <1> 	; 02/01/2022
   387 00000149 7408                <1> 	jz	short L9_10
   388 0000014B 80FA80              <1> 	cmp	dl, 80h
   389                              <1>         ;jna	L5
   390                              <1> 	;jmp	L13
   391                              <1> 	; 02/01/2022
   392 0000014E 7703                <1> 	ja	short L9_10
   393 00000150 E972FF              <1> 	jmp	L5
   394                              <1> L9_10:
   395 00000153 E90501              <1>         jmp     L13
   396                              <1> L10:
   397 00000156 FEC2                <1> 	inc 	dl
   398                              <1> 	; 25/12/2014
   399 00000158 8816[495C]          <1> 	mov	[drv], dl
   400 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   401 0000015E CD13                <1> 	int	13h	; (conventional function)
   402                              <1> 	;jc	L13
   403                              <1> 	; 02/01/2022
   404 00000160 72F1                <1> 	jc	short L9_10
   405                              <1> 	; 14/01/2015
   406 00000162 8A16[495C]          <1> 	mov	dl, [drv]
   407 00000166 52                  <1> 	push	dx
   408 00000167 51                  <1> 	push	cx
   409 00000168 E8FE00              <1> 	call	set_disk_parms
   410 0000016B 59                  <1> 	pop	cx
   411 0000016C 5A                  <1> 	pop	dx
   412                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   413                              <1> 	; 04/02/2016 (esi -> si)
   414                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   415                              <1> 	;		 ; at the '_end' of kernel.
   416                              <1> 	;mov	word [si], 30
   417                              <1> 	; 06/07/2016
   418 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   419                              <1> 	; 09/07/2016
   420 00000170 B81E00              <1> 	mov	ax, 001Eh
   421 00000173 8824                <1> 	mov	[si], ah ; 0
   422 00000175 46                  <1> 	inc	si
   423 00000176 8904                <1> 	mov	word [si], ax
   424                              <1>  	; word [si] = 30
   425                              <1> 	;
   426 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   427 0000017A CD13                <1> 	int	13h
   428                              <1>         ;jc	L13
   429                              <1> 	; 02/01/2022
   430 0000017C 72D5                <1> 	jc	short L9_10
   431                              <1> 	; 04/02/2016 (ebx -> bx)
   432                              <1> 	; 14/01/2015
   433                              <1> 	;sub	bx, bx
   434 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   435 00000180 88D3                <1> 	mov	bl, dl
   436 00000182 80EB80              <1> 	sub	bl, 80h
   437 00000185 81C3[4E5C]          <1> 	add	bx, hd0_type
   438 00000189 8A07                <1> 	mov 	al, [bx]
   439 0000018B 0C80                <1> 	or	al, 80h
   440 0000018D 8807                <1> 	mov 	[bx], al	
   441 0000018F 81EB[4C5C]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   442 00000193 81C3[6E5C]          <1> 	add	bx, drv.status
   443 00000197 8807                <1> 	mov	[bx], al
   444                              <1> 	; 04/02/2016 (eax -> ax)
   445 00000199 8B4410              <1> 	mov	ax, [si+16]
   446 0000019C 854412              <1> 	test	ax, [si+18]
   447 0000019F 7413                <1> 	jz	short L10_A0h 
   448                              <1> 			; 'CHS only' disks on EDD system 
   449                              <1> 			;  are reported with ZERO disk size
   450 000001A1 81EB[6E5C]          <1> 	sub	bx, drv.status
   451 000001A5 C1E302              <1> 	shl	bx, 2
   452 000001A8 81C3[525C]          <1> 	add	bx, drv.size ; disk size (in sectors)
   453 000001AC 8907                <1> 	mov	[bx], ax
   454 000001AE 8B4412              <1> 	mov	ax, [si+18]
   455                              <1> 	;mov	[bx], ax
   456                              <1> 	; 02/01/2022 (BugFix)
   457 000001B1 894702              <1> 	mov	[bx+2], ax
   458                              <1> 
   459                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   460                              <1> 	 ; for CHS disks (28/02/2015)
   461                              <1> 	; 30/12/2014
   462 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   463 000001B7 88D0                <1> 	mov	al, dl
   464 000001B9 83E003              <1> 	and 	ax, 3
   465 000001BC C0E005              <1> 	shl	al, 5 ; *32
   466 000001BF 01C7                <1> 	add 	di, ax
   467 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   468 000001C4 8EC0                <1> 	mov	es, ax
   469                              <1> 	;
   470 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   471 000001C8 88CC                <1> 	mov	ah, cl	
   472 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   473 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   474 000001CE AB                  <1> 	stosw		
   475 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   476 000001D1 FEC0                <1> 	inc	al
   477 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   478 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   479 000001D6 AA                  <1> 	stosb
   480 000001D7 8A440C              <1> 	mov	al, [si+12]
   481 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   482 000001DB 31C0                <1>  	xor	ax, ax
   483                              <1> 	;dec	ax	 ; 02/01/2015 
   484 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   485                              <1> 	;xor	al, al	 ; 02/01/2015	
   486 000001DE AA                  <1> 	stosb		 ; reserved
   487 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   488                              <1> 		         ; (do not disable retries, 
   489                              <1> 			 ; more than 8 heads)
   490 000001E1 AA                  <1> 	stosb
   491 000001E2 8B4404              <1> 	mov	ax, [si+4]
   492 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   493                              <1> 	;push	ax	 ; 02/01/2015
   494 000001E6 8A4408              <1> 	mov	al, [si+8]
   495 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   496 000001EA 29C0                <1> 	sub 	ax, ax
   497                              <1> 	;pop	ax	 ; 02/01/2015	
   498 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   499 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   500 000001EF 243F                <1> 	and 	al, 3Fh	
   501 000001F1 AA                  <1> 	stosb
   502                              <1> 	;sub	al, al	 ; checksum
   503                              <1> 	;stosb
   504                              <1> 	;
   505 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   506 000001F5 AD                  <1> 	lodsw
   507 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   508 000001F7 AD                  <1> 	lodsw
   509 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   510                              <1> 	;
   511                              <1> 	; checksum calculation
   512 000001F9 89FE                <1> 	mov	si, di
   513 000001FB 06                  <1> 	push	es
   514 000001FC 1F                  <1> 	pop	ds
   515                              <1> 	;mov	cx, 16
   516 000001FD B90F00              <1> 	mov 	cx, 15
   517 00000200 29CE                <1> 	sub	si, cx
   518 00000202 30E4                <1> 	xor	ah, ah
   519                              <1> 	;del	cl
   520                              <1> L11:		
   521 00000204 AC                  <1> 	lodsb
   522 00000205 00C4                <1> 	add	ah, al
   523 00000207 E2FB                <1> 	loop	L11
   524                              <1> 	;
   525 00000209 88E0                <1> 	mov	al, ah
   526 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   527 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   528                              <1> 	;
   529 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   530 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   531                              <1> 	;
   532                              <1> 	; 23/02/2015
   533 00000210 57                  <1> 	push	di
   534                              <1> 	; ES:DI points to DPTE (FDPTE) location
   535                              <1> 	;mov	cx, 8
   536 00000211 B108                <1> 	mov	cl, 8
   537 00000213 F3A5                <1> 	rep	movsw	
   538                              <1> 	;
   539                              <1> 	; 23/02/2015
   540                              <1> 	; (P)ATA drive and LBA validation
   541                              <1> 	; (invalidating SATA drives and setting
   542                              <1> 	; CHS type I/O for old type fixed disks)
   543 00000215 5B                  <1> 	pop	bx
   544 00000216 8CC8                <1> 	mov	ax, cs
   545 00000218 8ED8                <1> 	mov	ds, ax
   546 0000021A 268B07              <1> 	mov	ax, [es:bx]
   547 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   548 00000220 7418                <1> 	je	short L11a
   549 00000222 3D7001              <1> 	cmp	ax, 170h
   550 00000225 7413                <1> 	je	short L11a
   551                              <1> 	; invalidation 
   552                              <1> 	; (because base port address is not 1F0h or 170h)
   553 00000227 30FF                <1> 	xor	bh, bh
   554 00000229 88D3                <1> 	mov	bl, dl
   555 0000022B 80EB80              <1> 	sub	bl, 80h
   556 0000022E C687[4E5C]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   557 00000233 808F[705C]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   558 00000238 EB14                <1> 	jmp	short L11b
   559                              <1> L11a:	
   560                              <1> 	; LBA validation
   561 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   562 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   563 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   564                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   565 00000242 28FF                <1> 	sub	bh, bh
   566 00000244 88D3                <1> 	mov	bl, dl
   567 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   568 00000249 80A7[705C]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   569                              <1> 				; bit 0 = LBA ready bit
   570                              <1> 	; 'diskio' procedure will check this bit !
   571                              <1> L11b:
   572 0000024E 3A16[4A5C]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   573 00000252 7307                <1>         jnb     short L13
   574 00000254 E9FFFE              <1>         jmp     L10
   575                              <1> L12:
   576                              <1> 	; Restore data registers
   577 00000257 8CC8                <1> 	mov	ax, cs
   578 00000259 8ED8                <1> 	mov	ds, ax	
   579                              <1> L13:
   580                              <1> 	; 13/12/2014
   581 0000025B 0E                  <1> 	push	cs
   582 0000025C 07                  <1> 	pop	es
   583                              <1> L14:
   584 0000025D B411                <1> 	mov 	ah, 11h
   585 0000025F CD16                <1> 	int 	16h
   586                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   587                              <1> 	; 02/01/2022
   588 00000261 7447                <1> 	jz	short L16
   589 00000263 B010                <1> 	mov	al, 10h
   590 00000265 CD16                <1> 	int 	16h
   591 00000267 EBF4                <1> 	jmp 	short L14
   592                              <1> L15:
   593                              <1> 
   594                              <1> ; //////
   595                              <1> 
   596                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   597                              <1> %if 0
   598                              <1> 	; 24/11/2014
   599                              <1> 	; 19/11/2014
   600                              <1> 	; 14/11/2014
   601                              <1> 	; Temporary code for disk searching code check
   602                              <1> 	;
   603                              <1> 	; This code will show existing (usable) drives and also
   604                              <1> 	; will show EDD interface support status for hard disks		
   605                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   606                              <1> 	; no need to get it again in protected mode...) 
   607                              <1> 	;	
   608                              <1> 	; 13/11/2014
   609                              <1> 	mov	bx, 7
   610                              <1> 	mov	ah, 0Eh
   611                              <1> 	mov	al, [fd0_type]
   612                              <1> 	and	al, al
   613                              <1> 	jz	short L15a
   614                              <1> 	mov	dl, al
   615                              <1> 	mov	al, 'F'
   616                              <1> 	int 	10h
   617                              <1> 	mov	al, 'D'
   618                              <1> 	int 	10h
   619                              <1> 	mov	al, '0'
   620                              <1> 	int 	10h
   621                              <1> 	mov	al, ' '
   622                              <1> 	int	10h
   623                              <1> 	call	L15c
   624                              <1> 	mov	al, ' '
   625                              <1> 	int	10h
   626                              <1> 	;
   627                              <1> 	mov	al, [fd1_type]
   628                              <1> 	and	al, al
   629                              <1> 	jz	short L15a
   630                              <1> 	mov	dl, al
   631                              <1> 	mov	al, 'F'
   632                              <1> 	int 	10h
   633                              <1> 	mov	al, 'D'
   634                              <1> 	int 	10h
   635                              <1> 	mov	al, '1'
   636                              <1> 	int 	10h
   637                              <1> 	mov	al, ' '
   638                              <1> 	int	10h
   639                              <1> 	call	L15c
   640                              <1> 	mov	al, ' '
   641                              <1> 	int	10h
   642                              <1> 	mov	al, ' '
   643                              <1> 	int	10h
   644                              <1> L15a:
   645                              <1> 	mov	al, [hd0_type]
   646                              <1> 	and	al, al
   647                              <1> 	jz	short L15b
   648                              <1> 	mov	dl, al
   649                              <1> 	mov	al, 'H'
   650                              <1> 	int 	10h
   651                              <1> 	mov	al, 'D'
   652                              <1> 	int 	10h
   653                              <1> 	mov	al, '0'
   654                              <1> 	int 	10h
   655                              <1> 	mov	al, ' '
   656                              <1> 	int 	10h
   657                              <1> 	call	L15c
   658                              <1> 	mov	al, ' '
   659                              <1> 	int	10h
   660                              <1> 	;
   661                              <1> 	mov	al, [hd1_type]
   662                              <1> 	and	al, al
   663                              <1> 	jz	short L15b
   664                              <1> 	mov	dl, al
   665                              <1> 	mov	al, 'H'
   666                              <1> 	int 	10h
   667                              <1> 	mov	al, 'D'
   668                              <1> 	int 	10h
   669                              <1> 	mov	al, '1'
   670                              <1> 	int 	10h
   671                              <1> 	mov	al, ' '
   672                              <1> 	int 	10h
   673                              <1> 	call	L15c
   674                              <1> 	mov	al, ' '
   675                              <1> 	int	10h
   676                              <1> 	;
   677                              <1> 	mov	al, [hd2_type]
   678                              <1> 	and	al, al
   679                              <1> 	jz	short L15b
   680                              <1> 	mov	dl, al
   681                              <1> 	mov	al, 'H'
   682                              <1> 	int 	10h
   683                              <1> 	mov	al, 'D'
   684                              <1> 	int 	10h
   685                              <1> 	mov	al, '2'
   686                              <1> 	int 	10h
   687                              <1> 	mov	al, ' '
   688                              <1> 	int 	10h
   689                              <1> 	call	L15c
   690                              <1> 	mov	al, ' '
   691                              <1> 	int	10h
   692                              <1> 	;
   693                              <1> 	mov	al, [hd3_type]
   694                              <1> 	and	al, al
   695                              <1> 	jz	short L15b
   696                              <1> 	mov	dl, al
   697                              <1> 	mov	al, 'H'
   698                              <1> 	int 	10h
   699                              <1> 	mov	al, 'D'
   700                              <1> 	int 	10h
   701                              <1> 	mov	al, '3'
   702                              <1> 	int 	10h
   703                              <1> 	mov	al, ' '
   704                              <1> 	int 	10h
   705                              <1> 	call	L15c
   706                              <1> 	mov	al, ' '
   707                              <1> 	int	10h
   708                              <1> 	;
   709                              <1> L15b:
   710                              <1> 	mov	al, 0Dh
   711                              <1> 	int 	10h	
   712                              <1> 	mov	al, 0Ah
   713                              <1> 	int 	10h
   714                              <1> 	;;xor	ah, ah
   715                              <1> 	;;int 	16h	
   716                              <1> 	;
   717                              <1>         ;jmp	L16  ; jmp short L16
   718                              <1>         ; 02/01/2022
   719                              <1> 	jmp	short L16
   720                              <1> 	;
   721                              <1> L15c:
   722                              <1> 	mov	dh, dl
   723                              <1> 	shr	dh, 4
   724                              <1> 	add	dh, 30h
   725                              <1> 	and	dl, 15
   726                              <1> 	add	dl, 30h
   727                              <1> 	mov	al, dh
   728                              <1> 	int	10h
   729                              <1> 	mov	al, dl
   730                              <1> 	int	10h
   731                              <1> 	retn
   732                              <1> 	;
   733                              <1> 	; end of temporary code for disk searching code check
   734                              <1> 
   735                              <1> %endif
   736                              <1> 
   737                              <1> ; //////
   738                              <1> 
   739                              <1> set_disk_parms:
   740                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
   741                              <1> 	; 09/05/2022
   742                              <1> 	;	disksize = cylinders*spt*heads (*)
   743                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders)
   744                              <1> 	;
   745                              <1> 	; 04/02/2016 (ebx -> bx)
   746                              <1> 	; 10/07/2015
   747                              <1> 	; 14/01/2015
   748                              <1> 	;push	bx
   749 00000269 28FF                <1> 	sub	bh, bh
   750 0000026B 8A1E[495C]          <1> 	mov	bl, [drv]
   751 0000026F 80FB80              <1> 	cmp	bl, 80h
   752 00000272 7203                <1> 	jb	short sdp0
   753 00000274 80EB7E              <1> 	sub	bl, 7Eh
   754                              <1> sdp0:	
   755 00000277 81C3[6E5C]          <1> 	add	bx, drv.status
   756 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   757                              <1> 	;
   758 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   759 00000280 88CC                <1> 	mov	ah, cl ; 
   760 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   761 00000285 81EB[6E5C]          <1> 	sub	bx, drv.status
   762 00000289 D0E3                <1> 	shl	bl, 1
   763                              <1> 	; 12/07/2022
   764                              <1> 	;add	bx, drv.cylinders
   765 0000028B 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count
   766                              <1> 	;mov	[bx], ax
   767 0000028C 50                  <1> 	push	ax ; ** cylinders
   768                              <1> 	;sub	bx, drv.cylinders
   769                              <1> 	;add	bx, drv.heads
   770 0000028D 30E4                <1> 	xor	ah, ah
   771 0000028F 88F0                <1> 	mov	al, dh ; heads
   772 00000291 40                  <1> 	inc	ax
   773                              <1> 	;mov	[bx], ax
   774                              <1>         ;sub	bx, drv.heads
   775                              <1>         ;add	bx, drv.spt
   776 00000292 30ED                <1> 	xor	ch, ch
   777 00000294 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   778                              <1> 	;mov	[bx], cx
   779                              <1>         ;sub	bx, drv.spt
   780 00000297 D1E3                <1> 	shl	bx, 1
   781 00000299 81C3[525C]          <1> 	add	bx, drv.size ; disk size (in sectors)
   782                              <1> 	; LBA size = cylinders * heads * secpertrack
   783 0000029D F7E1                <1> 	mul	cx 
   784 0000029F 89C2                <1> 	mov	dx, ax	; heads*spt
   785 000002A1 58                  <1> 	pop	ax ; ** cylinders
   786                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   787                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   788 000002A2 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)
   789 000002A4 8907                <1> 	mov	[bx], ax
   790 000002A6 895702              <1> 	mov	[bx+2], dx
   791                              <1> 	;
   792                              <1> 	;pop	bx
   793 000002A9 C3                  <1> 	retn
   794                              <1> 
   795                              <1> ;align 2
   796                              <1> 
   797                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   798                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   799                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   800                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   801                              <1> 
   802                              <1> ;last_drv:
   803                              <1> ;	db  0
   804                              <1> ;drv_status:
   805                              <1> ;	db  0,0,0,0,0,0
   806                              <1> ;	db 0
   807                              <1> 
   808                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   809                              <1> 
   810                              <1> L16:
   239                                  
   240                                  	; 10/11/2014
   241 000002AA FA                           	cli	; Disable interrupts (clear interrupt flag)
   242                                  		; Reset Interrupt MASK Registers (Master&Slave)
   243                                  	;mov	al, 0FFh	; mask off all interrupts
   244                                  	;out	21h, al		; on master PIC (8259)
   245                                  	;jmp 	$+2  ; (delay)
   246                                  	;out	0A1h, al	; on slave PIC (8259)
   247                                  	;
   248                                  	; Disable NMI 
   249 000002AB B080                    	mov   	al, 80h 
   250 000002AD E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   251                                  	;23/02/2015
   252 000002AF 90                      	nop			;
   253                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   254                                  				; for preventing unknown state (!?)
   255                                  
   256                                  	; 02/01/2022
   257                                  	%define KERNELFSIZE KEND-KSTART 
   258                                  	;
   259                                   	; 20/08/2014
   260                                  	; Moving the kernel 64 KB back (to physical address 0)
   261                                  	; DS = CS = 1000h
   262                                  	; 05/11/2014
   263 000002B0 31C0                    	xor	ax, ax
   264 000002B2 8EC0                    	mov	es, ax ; ES = 0
   265                                  	;
   266                                  	;;mov	cx, (KEND - KLOAD)/4
   267                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   268 000002B4 B95E2F                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   269 000002B7 31F6                    	xor	si, si
   270 000002B9 31FF                    	xor	di, di
   271                                  	;rep	movsd
   272 000002BB F3A5                    	rep	movsw ; 02/01/2022
   273                                  	;
   274 000002BD 06                      	push	es ; 0
   275 000002BE 68[C202]                	push	L17
   276 000002C1 CB                      	retf
   277                                  	;
   278                                  L17:
   279                                  	; Turn off the floppy drive motor
   280 000002C2 BAF203                          mov     dx, 3F2h
   281 000002C5 EE                              out     dx, al ; 0 ; 31/12/2013
   282                                  
   283                                  	; Enable access to memory above one megabyte
   284                                  L18:
   285 000002C6 E464                    	in	al, 64h
   286 000002C8 A802                    	test	al, 2
   287 000002CA 75FA                            jnz     short L18
   288 000002CC B0D1                    	mov	al, 0D1h	; Write output port
   289 000002CE E664                    	out	64h, al
   290                                  L19:
   291 000002D0 E464                    	in	al, 64h
   292 000002D2 A802                    	test	al, 2
   293 000002D4 75FA                            jnz     short L19
   294 000002D6 B0DF                    	mov	al, 0DFh	; Enable A20 line
   295 000002D8 E660                    	out	60h, al
   296                                  ;L20:
   297                                  	;
   298                                  	; Load global descriptor table register
   299                                  
   300                                          ;mov     ax, cs
   301                                          ;mov     ds, ax
   302                                  
   303 000002DA 2E0F0116[7059]                  lgdt    [cs:gdtd]
   304                                  
   305 000002E0 0F20C0                          mov     eax, cr0
   306                                  	; or 	eax, 1
   307 000002E3 40                      	inc     ax
   308 000002E4 0F22C0                  	mov     cr0, eax
   309                                  
   310                                  	; Jump to 32 bit code
   311                                  	
   312 000002E7 66                      	db 66h 			; Prefix for 32-bit
   313 000002E8 EA                      	db 0EAh 		; Opcode for far jump
   314 000002E9 [EF020000]              	dd StartPM 		; Offset to start, 32-bit
   315                                  				; (1000h:StartPM = StartPM + 10000h)
   316 000002ED 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   317                                  				; assuming that StartPM resides in code32
   318                                  
   319                                  [BITS 32] 
   320                                  
   321                                  StartPM:
   322                                  	; Kernel Base Address = 0 ; 30/12/2013
   323 000002EF 66B81000                	mov ax, KDATA           ; Save data segment identifier
   324 000002F3 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   325 000002F5 8EC0                           	mov es, ax              ; Move data segment into ES register
   326 000002F7 8EE0                           	mov fs, ax              ; Move data segment into FS register
   327 000002F9 8EE8                          	mov gs, ax              ; Move data segment into GS register
   328 000002FB 8ED0                            mov ss, ax              ; Move data segment into SS register
   329 000002FD BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   330                                  
   331                                  clear_bss: ; Clear uninitialized data area
   332                                  	; 11/03/2015
   333 00000302 31C0                    	xor	eax, eax ; 0
   334                                  	;mov	ecx, (bss_end - bss_start)/4
   335                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   336                                  	; 02/01/2022
   337 00000304 B9C1060000              	mov	ecx, BSS_SIZE/4
   338 00000309 BF[C05E0000]            	mov	edi, bss_start
   339 0000030E F3AB                    	rep	stosd  		
   340                                  
   341                                  memory_init:
   342                                  	; Initialize memory allocation table and page tables
   343                                  	;
   344                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   345                                  	; 16/11/2014
   346                                  	; 15/11/2014
   347                                  	; 07/11/2014
   348                                  	; 06/11/2014
   349                                  	; 05/11/2014
   350                                  	; 04/11/2014
   351                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   352                                  	;
   353                                  ;	xor	eax, eax
   354                                  ;	xor 	ecx, ecx
   355 00000310 B108                    	mov	cl, 8
   356 00000312 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   357 00000317 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   358                                  				   ; for the first 1 MB memory
   359                                  	;
   360 00000319 8B0D[B45E0000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   361                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   362                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   363                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   364 0000031F C1E902                  	shr	ecx, 2	; 02/01/2022
   365 00000322 890D[30610000]          	mov	[free_pages], ecx
   366 00000328 8B15[B85E0000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   367                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   368                                  				   ; between 16 MB and 4 GB.
   369                                  	;or	dx, dx
   370 0000032E 09D2                    	or	edx, edx ; 02/01/2022
   371 00000330 7412                    	jz	short mi_0
   372                                  	;
   373                                  	;mov	ax, dx
   374 00000332 89D0                    	mov	eax, edx ; 02/01/2022
   375 00000334 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   376 00000337 0105[30610000]          	add	[free_pages], eax
   377 0000033D 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   378 00000342 EB06                    	jmp	short mi_1
   379                                  mi_0:
   380                                  	;mov	ax, cx
   381 00000344 89C8                    	mov	eax, ecx ; 02/01/2022	 
   382 00000346 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   383                                  mi_1:
   384 0000034A A3[2C610000]            	mov	[memory_size], eax ; Total available memory in pages
   385                                  				   ; 1 alloc. tbl. bit = 1 memory page
   386                                  				   ; 32 allocation bits = 32 mem. pages
   387                                  	;
   388 0000034F 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   389 00000354 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   390                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   391                                  				   ;  --> x M.A.T. pages, if y = 0
   392                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   393 00000357 A3[40610000]            	mov	[mat_size], eax ; 02/01/2022
   394 0000035C C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   395                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   396 0000035F 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   397                                  	; Set/Calculate Kernel's Page Directory Address
   398 00000361 81C300001000            	add	ebx, MEM_ALLOC_TBL
   399 00000367 891D[28610000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   400                                  				   ; just after the last M.A.T. page
   401                                  	;
   402 0000036D 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   403 00000370 A3[38610000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   404                                  	;			   ; (allocation status search must be
   405                                  				   ; stopped after here)
   406 00000375 31C0                    	xor	eax, eax
   407 00000377 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   408                                  	;push	cx
   409 00000378 51                      	push	ecx ; 02/01/2022 
   410 00000379 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   411                                  				   ; count of 32 allocation bits
   412 0000037C F3AB                    	rep	stosd
   413                                  	;pop	cx
   414 0000037E 59                      	pop	ecx ; 02/01/2022
   415 0000037F 40                      	inc	eax		   ; 0
   416 00000380 80E11F                  	and	cl, 31		   ; remain bits
   417 00000383 7412                    	jz	short mi_4
   418 00000385 8907                    	mov	[edi], eax	   ; reset
   419                                  mi_2:
   420 00000387 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   421 0000038A FEC9                    	dec	cl
   422 0000038C 7404                    	jz	short mi_3
   423 0000038E FEC0                    	inc	al
   424 00000390 EBF5                    	jmp	short mi_2
   425                                  mi_3:
   426 00000392 28C0                    	sub	al, al	   	   ; 0
   427 00000394 83C704                  	add	edi, 4		   ; 15/11/2014
   428                                  mi_4:
   429 00000397 09D2                    	or	edx, edx ; 02/01/2022
   430                                  	;or	dx, dx		  ; check 16M to 4G memory space
   431 00000399 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   432                                  	;	
   433 0000039B B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   434                                  	;	
   435 000003A0 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   436 000003A2 7405                    	jz	short mi_5	  ; jump if EDI points to 
   437                                  				  ;         end of first 16 MB	
   438                                  	;shr	ecx, 1		  ; convert to dword count
   439                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   440 000003A4 C1E902                  	shr	ecx, 2	; 02/01/2022
   441 000003A7 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   442                                  				  ; (memory hole under 16 MB)
   443                                  mi_5:
   444 000003A9 89D1                    	mov	ecx, edx ; 02/01/2022
   445                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   446 000003AB D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   447 000003AD 9C                      	pushf			  ; 16/11/2014		
   448 000003AE 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   449 000003AF F3AB                    	rep	stosd
   450 000003B1 40                      	inc	eax		  ; 0
   451 000003B2 9D                      	popf			  ; 16/11/2014
   452 000003B3 7305                    	jnc	short mi_6
   453 000003B5 6648                    	dec	ax		  ; eax = 0000FFFFh
   454 000003B7 AB                      	stosd
   455 000003B8 6640                    	inc	ax		  ; 0		
   456                                  mi_6:
   457 000003BA 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   458 000003BC 7309                    	jnb	short mi_7	  ; end of memory allocation table
   459                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   460 000003BE 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   461 000003C0 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   462                                  	;shr	ecx, 1		  ; to dword count
   463                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   464 000003C2 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   465 000003C5 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   466                                  mi_7:
   467                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   468 000003C7 BA00001000              	mov	edx, MEM_ALLOC_TBL
   469                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   470                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   471 000003CC 8B0D[40610000]          	mov	ecx, [mat_size] ; 02/01/2022
   472                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   473 000003D2 89D7                    	mov	edi, edx
   474 000003D4 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   475                                  				  ; byte offset in M.A.T.
   476                                  				  ; (1 M.A.T. byte points to 
   477                                  				  ;	      32768 bytes)
   478                                  				  ; Note: MEM_ALLOC_TBL address 
   479                                  				  ; must be aligned on 128 KB 
   480                                  				  ; boundary!
   481 000003D7 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   482                                  	; eax = 0
   483 000003D9 290D[30610000]          	sub	[free_pages], ecx ; 07/11/2014
   484                                  mi_8:
   485 000003DF 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   486                                  	;dec	bl
   487 000003E2 FEC9                    	dec	cl
   488 000003E4 7404                    	jz	short mi_9
   489 000003E6 FEC0                    	inc	al
   490 000003E8 EBF5                    	jmp	short mi_8
   491                                  mi_9:
   492                                  	;
   493                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   494                                  	;		(allocate pages for system page tables)
   495                                  
   496                                  	; edx = MEM_ALLOC_TBL
   497 000003EA 8B0D[2C610000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   498 000003F0 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   499 000003F6 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   500                                  				 ; page table count (PDE count)
   501                                  	;
   502 000003F9 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   503                                  	;
   504 000003FA 41                      	inc	ecx		 ; +1 for kernel page directory	
   505                                  	;
   506 000003FB 290D[30610000]          	sub	[free_pages], ecx ; 07/11/2014
   507                                  	;
   508 00000401 8B35[28610000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   509 00000407 C1EE0C                  	shr	esi, 12		 ; convert to page number
   510                                  mi_10:
   511 0000040A 89F0                    	mov	eax, esi	 ; allocation bit offset
   512 0000040C 89C3                    	mov	ebx, eax
   513 0000040E C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   514 00000411 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   515                                  				 ;   to align on dword boundary
   516 00000414 83E01F                  	and	eax, 31		 ; set allocation bit position 
   517                                  				 ;  (bit 0 to bit 31)
   518                                  	;
   519 00000417 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   520                                  	;
   521 00000419 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   522                                  	;
   523 0000041C 46                      	inc	esi		 ; next page table
   524 0000041D E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   525                                  				 ; (ecx = page table count + 1)
   526                                  	;
   527 0000041F 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   528                                  	;
   529                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   530                                  	;
   531                                  	; Initialize Kernel's Page Directory
   532 00000420 8B3D[28610000]          	mov	edi, [k_page_dir]
   533 00000426 89F8                    	mov	eax, edi
   534 00000428 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   535                                  		     	      ; supervisor + read&write + present
   536 0000042A 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   537                                  mi_11:
   538 0000042C 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   539                                  			        ; EAX points to next page table
   540 00000431 AB                      	stosd
   541 00000432 E2F8                    	loop	mi_11
   542 00000434 29C0                    	sub	eax, eax	; Empty PDE
   543                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   544                                  	; 02/01/2022
   545 00000436 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   546 00000438 29D1                    	sub	ecx, edx
   547 0000043A 7402                    	jz	short mi_12
   548 0000043C F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   549                                  	;
   550                                  	; Initialization of Kernel's Page Directory is OK, here.
   551                                  mi_12:
   552                                  	; Initialize Kernel's Page Tables
   553                                  	;
   554                                  	; (EDI points to address of page table 0)
   555                                  	; eax = 0
   556 0000043E 8B0D[2C610000]          	mov	ecx, [memory_size] ; memory size in pages
   557 00000444 89CA                    	mov	edx, ecx	; (***)
   558 00000446 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   559                                  			     ; supervisor + read&write + present
   560                                  mi_13:
   561 00000448 AB                      	stosd
   562 00000449 0500100000              	add	eax, 4096	
   563 0000044E E2F8                    	loop	mi_13
   564                                  	; 02/01/2022
   565 00000450 66B9FF03                	mov	cx, 1023
   566 00000454 21CA                    	and	edx, ecx
   567                                  	;and	dx, 1023	; (***)
   568 00000456 7407                    	jz	short mi_14
   569                                  	;mov	cx, 1024	
   570                                  	; 02/01/2022
   571                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   572 00000458 41                      	inc	ecx ; ecx = 1024
   573 00000459 29D1                    	sub	ecx, edx
   574                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   575 0000045B 31C0                    	xor	eax, eax
   576 0000045D F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   577                                  				; of the last page table
   578                                  mi_14:
   579                                  	;  Initialization of Kernel's Page Tables is OK, here.
   580                                  	;
   581 0000045F 89F8                    	mov	eax, edi	; end of the last page table page
   582                                  			        ; (beginging of user space pages)
   583 00000461 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   584 00000464 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   585                                  				; aligning on dword boundary
   586                                  	 
   587 00000466 A3[3C610000]            	mov	[first_page], eax
   588 0000046B A3[34610000]            	mov	[next_page], eax ; The first free page pointer
   589                                  				 ; for user programs
   590                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   591                                  	;
   592                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   593                                  	;
   594                                  	
   595                                  	; Enable paging
   596                                  	;
   597 00000470 A1[28610000]                    mov     eax, [k_page_dir]
   598 00000475 0F22D8                  	mov	cr3, eax
   599 00000478 0F20C0                  	mov	eax, cr0
   600 0000047B 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   601 00000480 0F22C0                  	mov	cr0, eax
   602                                          ;jmp    KCODE:StartPMP
   603                                  
   604 00000483 EA                      	db 0EAh 		; Opcode for far jump
   605 00000484 [8A040000]                      dd StartPMP		; 32 bit offset
   606 00000488 0800                    	dw KCODE		; kernel code segment descriptor
   607                                  
   608                                  StartPMP:
   609                                  	; 06/11//2014
   610                                  	; Clear video page 0
   611                                  	;
   612                                  	; Temporary Code
   613                                  	;
   614                                  	;mov	ecx, 80*25/2
   615 0000048A 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   616 0000048E BF00800B00              	mov	edi, 0B8000h
   617 00000493 57                      	push	edi ; * ; 02/01/2022
   618 00000494 31C0                    	xor	eax, eax	; black background, black fore color
   619 00000496 F3AB                    	rep	stosd
   620                                  	
   621                                  	; 19/08/2014
   622                                  	; Kernel Base Address = 0
   623                                  	; It is mapped to (physically) 0 in the page table.
   624                                  	; So, here is exactly 'StartPMP' address.
   625                                  	;
   626                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   627                                  	;;mov	esi, msgPM
   628                                  	;; 14/08/2015 (kernel version message will appear
   629                                  	;;	       when protected mode and paging is enabled)
   630 00000498 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   631 0000049A BE[845C0000]            	mov	esi, msgKVER
   632 0000049F 5F                      	pop	edi ; * ; 02/01/2022
   633                                  	;mov	edi, 0B8000h ; 27/08/2014
   634                                  	; 20/08/2014
   635 000004A0 E891010000              	call	printk
   636                                  
   637                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   638                                  	; // Set IRQ offsets
   639                                  	;
   640                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   641                                  	;
   642                                  					;; ICW1
   643 000004A5 B011                    	mov	al, 11h			; Initialization sequence
   644 000004A7 E620                    	out	20h, al			; 	8259A-1
   645                                  	; jmp 	$+2
   646 000004A9 E6A0                    	out	0A0h, al		; 	8259A-2
   647                                  					;; ICW2
   648 000004AB B020                    	mov	al, 20h			; Start of hardware ints (20h)
   649 000004AD E621                    	out	21h, al			;	for 8259A-1
   650                                  	; jmp 	$+2
   651 000004AF B028                    	mov	al, 28h			; Start of hardware ints (28h)
   652 000004B1 E6A1                    	out	0A1h, al		; 	for 8259A-2
   653                                  					;
   654 000004B3 B004                    	mov	al, 04h			;; ICW3
   655 000004B5 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   656                                  	; jmp 	$+2
   657 000004B7 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   658 000004B9 E6A1                    	out	0A1h, al		;
   659                                  					;; ICW4
   660 000004BB B001                    	mov	al, 01h	 		;
   661 000004BD E621                    	out	21h, al			; 	8086 mode, normal EOI	
   662                                  	; jmp 	$+2
   663 000004BF E6A1                    	out	0A1h, al		;	for both chips.
   664                                  
   665                                  	;mov	al, 0FFh	; mask off all interrupts for now
   666                                  	;out	21h, al
   667                                  	;; jmp 	$+2
   668                                  	;out	0A1h, al
   669                                  
   670                                  	; 02/04/2015
   671                                  	; 26/03/2015 System call (INT 30h) modification
   672                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   673                                  	;
   674                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   675                                  	;  setup_idt:
   676                                  	;
   677                                          ;; 16/02/2015
   678                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   679                                  	; 21/08/2014 (timer_int)
   680 000004C1 BE[7C590000]            	mov	esi, ilist
   681 000004C6 8D3D[C05E0000]          	lea	edi, [idt]
   682                                  	; 26/03/2015
   683 000004CC B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   684                                  	; 02/04/2015
   685 000004D1 BB00000800              	mov	ebx,  80000h
   686                                  rp_sidt1:
   687 000004D6 AD                      	lodsd
   688 000004D7 89C2                    	mov	edx, eax
   689 000004D9 66BA008E                	mov	dx, 8E00h
   690 000004DD 6689C3                  	mov	bx, ax
   691 000004E0 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   692                                         			        ; /* interrupt gate - dpl=0, present */
   693 000004E2 AB                      	stosd	; selector & offset bits 0-15 	
   694 000004E3 89D0                    	mov	eax, edx
   695 000004E5 AB                      	stosd	; attributes & offset bits 16-23
   696 000004E6 E2EE                    	loop	rp_sidt1
   697 000004E8 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   698                                  rp_sidt2:
   699 000004EA AD                      	lodsd
   700 000004EB 21C0                    	and	eax, eax
   701 000004ED 7413                    	jz	short rp_sidt3
   702 000004EF 89C2                    	mov	edx, eax
   703 000004F1 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   704 000004F5 6689C3                  	mov	bx, ax
   705 000004F8 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   706 000004FA AB                      	stosd
   707 000004FB 89D0                    	mov	eax, edx
   708 000004FD AB                      	stosd
   709 000004FE E2EA                    	loop	rp_sidt2
   710 00000500 EB16                    	jmp	short sidt_OK
   711                                  rp_sidt3:
   712 00000502 B8[5A090000]            	mov	eax, ignore_int
   713 00000507 89C2                    	mov	edx, eax
   714 00000509 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   715 0000050D 6689C3                  	mov	bx, ax
   716 00000510 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   717                                  rp_sidt4:
   718 00000512 AB                      	stosd
   719 00000513 92                      	xchg	eax, edx
   720 00000514 AB                      	stosd
   721 00000515 92                      	xchg	edx, eax
   722 00000516 E2FA                    	loop	rp_sidt4
   723                                  sidt_OK: 
   724 00000518 0F011D[76590000]        	lidt 	[idtd]
   725                                  	;
   726                                  	; TSS descriptor setup ; 24/03/2015
   727 0000051F B8[C0600000]            	mov	eax, task_state_segment
   728 00000524 66A3[6A590000]          	mov	[gdt_tss0], ax
   729 0000052A C1C010                  	rol	eax, 16
   730 0000052D A2[6C590000]            	mov	[gdt_tss1], al
   731 00000532 8825[6F590000]          	mov	[gdt_tss2], ah
   732 00000538 66C705[26610000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   732 00000540 00                 
   733                                  		; 
   734                                  		; IO Map Base address (When this address points
   735                                  		; to end of the TSS, CPU does not use IO port 
   736                                  		; permission bit map for RING 3 IO permissions, 
   737                                  		; access to any IO ports in ring 3 will be forbidden.)
   738                                   		;
   739                                  	;mov	[tss.esp0], esp ; TSS offset 4
   740                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   741 00000541 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   742                                  			 ; occurs (or a system call -software INT- is requested)
   743                                  			 ; while cpu running in ring 3 (in user mode).				
   744                                  			 ; (Kernel stack pointer and segment will be loaded
   745                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   746 00000545 0F00D8                  	ltr	ax  ; Load task register
   747                                  	;
   748                                  esp0_set0:
   749                                  	; 30/07/2015
   750 00000548 8B0D[2C610000]          	mov 	ecx, [memory_size] ; memory size in pages
   751 0000054E C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   752 00000551 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   753                                  			  ; (kernel mode virtual address)
   754 00000557 7605                    	jna	short esp0_set1
   755                                  	;
   756                                  	; If available memory > CORE (end of the 1st 4 MB)
   757                                  	; set stack pointer to CORE
   758                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   759                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   760 00000559 B900004000              	mov	ecx, CORE
   761                                  esp0_set1:
   762 0000055E 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   763                                  esp0_set_ok:
   764                                  	; 30/07/2015 (**tss.esp0**) 
   765 00000560 8925[C4600000]          	mov	[tss.esp0], esp
   766 00000566 66C705[C8600000]10-             mov     word [tss.ss0], KDATA
   766 0000056E 00                 
   767                                  	; 14/08/2015
   768                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   769                                  	;
   770                                  	;cli	; Disable interrupts (for CPU)
   771                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   772                                  	;
   773 0000056F 30C0                    	xor	al, al		; Enable all hardware interrupts!
   774 00000571 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   775 00000573 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   776 00000575 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   777                                  				; (Even if related hardware component
   778                                  				;  does not exist!)
   779                                  	; Enable NMI 
   780 00000577 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   781 00000579 E670                    	out  	70h, al
   782                                  	; 23/02/2015
   783 0000057B 90                      	nop
   784 0000057C E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   785                                  				; for preventing unknown state (!?)
   786                                  	;
   787                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   788                                  	;
   789                                  	; 02/09/2014
   790                                  	;xor	bx, bx
   791                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   792                                  	; 27/02/2022	
   793 0000057E 31DB                    	xor	ebx, ebx
   794 00000580 31D2                    	xor	edx, edx
   795 00000582 B602                    	mov	dh, 2
   796 00000584 E81D0E0000              	call	set_cpos
   797                                  	;
   798                                  	; 06/11/2014
   799                                  	; Temporary Code
   800                                  	;
   801 00000589 E8920F0000              	call	memory_info
   802                                  	; 14/08/2015
   803                                  	;call getch ; 28/02/2015
   804                                  drv_init:
   805 0000058E FB                      	sti	; Enable Interrupts 
   806                                  	; 06/02/2015
   807 0000058F 8B15[4E5C0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   808 00000595 668B1D[4C5C0000]        	mov	bx, [fd0_type] ; fd0, fd1
   809                                  	; 22/02/2015
   810 0000059C 6621DB                  	and	bx, bx
   811 0000059F 751B                    	jnz	short di1
   812                                  	;
   813 000005A1 09D2                    	or 	edx, edx
   814 000005A3 7529                    	jnz	short di2
   815                                  	;
   816                                  setup_error:
   817 000005A5 BE[6D5D0000]            	mov 	esi, setup_error_msg
   818                                  psem:	
   819 000005AA AC                      	lodsb
   820 000005AB 08C0                    	or	al, al
   821                                  	;jz	short haltx ; 22/02/2015
   822 000005AD 7426                    	jz	short di3
   823 000005AF 56                      	push	esi
   824 000005B0 31DB                    	xor	ebx, ebx ; 0
   825                                  			; Video page 0 (bl=0)
   826 000005B2 B407                    	mov	ah, 07h ; Black background, 
   827                                  			; light gray forecolor
   828 000005B4 E8E30C0000              	call	write_tty
   829 000005B9 5E                      	pop	esi
   830 000005BA EBEE                    	jmp	short psem
   831                                  
   832                                  di1:
   833                                  	; supress 'jmp short T6'
   834                                  	;  (activate fdc motor control code)
   835 000005BC 66C705[B7060000]90-     	mov	word [T5], 9090h ; nop
   835 000005C4 90                 
   836                                  	;
   837                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   838                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   839                                  	;stosw
   840                                  	;mov 	ax, cs
   841                                  	;stosw
   842                                  	;; 16/02/2015
   843                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   844                                  	;
   845 000005C5 E8FC180000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   846                                  	;
   847 000005CA 09D2                    	or	edx, edx
   848 000005CC 7407                            jz      short di3
   849                                  di2:
   850 000005CE E825190000              	call   	DISK_SETUP	; Initialize Fixed Disks
   851 000005D3 72D0                            jc      short setup_error
   852                                  di3:
   853 000005D5 E81A0F0000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   854                                  	;
   855 000005DA E8BA520000              	call	display_disks ; 07/03/2015  (Temporary)
   856                                  ;haltx:
   857                                  	; 14/08/2015
   858                                  	;call	getch ; 22/02/2015
   859 000005DF FB                      	sti	; Enable interrupts (for CPU)
   860                                  	; 14/08/2015
   861                                  	;mov 	ecx, 0FFFFFFFh
   862                                  	; 24/12/2021
   863 000005E0 B9FFFF2F00              	mov 	ecx, 02FFFFFh
   864                                  md_info_msg_wait:
   865 000005E5 51                      	push 	ecx
   866 000005E6 B001                    	mov	al, 1
   867 000005E8 8A25[56610000]          	mov 	ah, [ptty] ; active (current) video page
   868 000005EE E8914F0000              	call	getc_n
   869 000005F3 59                      	pop	ecx
   870 000005F4 7502                    	jnz	short md_info_msg_ok
   871 000005F6 E2ED                    	loop	md_info_msg_wait
   872                                  md_info_msg_ok:
   873                                  	; 30/06/2015
   874 000005F8 E8B9220000              	call	sys_init
   875                                  	;
   876                                  	;jmp 	cpu_reset ; 22/02/2015
   877                                  hang:
   878                                  	; 24/12/2021
   879 000005FD 29C0                    	sub	eax, eax
   880                                  _hang:	
   881                                  	; 23/02/2015
   882                                  	;sti			; Enable interrupts
   883 000005FF F4                      	hlt
   884                                  	;
   885                                  	;nop
   886                                  	;; 03/12/2014
   887                                  	;; 28/08/2014
   888                                  	;mov	ah, 11h
   889                                  	;call	getc
   890                                  	;jz      _c8
   891                                  	;
   892                                  	; 23/02/2015
   893                                  	; 06/02/2015
   894                                  	; 07/09/2014
   895 00000600 31DB                    	xor	ebx, ebx
   896 00000602 8A1D[56610000]          	mov	bl, [ptty]	; active_page
   897 00000608 89DE                    	mov	esi, ebx
   898                                  	;shl 	si, 1
   899                                  	; 17/07/2022
   900 0000060A D1E6                    	shl	esi, 1
   901 0000060C 81C6[58610000]          	add	esi, ttychr
   902 00000612 668B06                  	mov	ax, [esi]
   903                                  	;and	ax, ax
   904                                  	;;jz	short _c8
   905                                  	;jz	short hang
   906                                  	; 24/12/2021
   907 00000615 21C0                    	and	eax, eax
   908 00000617 74E6                    	jz	short _hang
   909 00000619 66C7060000              	mov	word [esi], 0
   910 0000061E 80FB03                  	cmp	bl, 3		; Video page 3
   911                                  	;jb	short _c8
   912 00000621 72DA                    	jb	short hang
   913                                  	;	
   914                                  	; 02/09/2014
   915 00000623 B40E                    	mov	ah, 0Eh		; Yellow character 
   916                                  				; on black background
   917                                  	; 24/12/2021 (32 bit reg push-pop)
   918                                  	; 07/09/2014
   919                                  nxtl:
   920 00000625 53                      	push	ebx
   921                                  	;
   922                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   923                                  				; bh = 0 (video mode)
   924                                  				; Retro UNIX 386 v1 - Video Mode 0
   925                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   926 00000626 50                      	push	eax
   927 00000627 E8700C0000              	call 	write_tty
   928 0000062C 58                      	pop	eax
   929                                  	;pop	bx
   930 0000062D 5B                      	pop	ebx
   931 0000062E 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   932                                  	;jne	short _c8
   933 00000630 75CB                    	jne	short hang
   934 00000632 B00A                    	mov	al, 0Ah		; next line
   935 00000634 EBEF                    	jmp	short nxtl
   936                                  	
   937                                  ;_c8:
   938                                  ;	; 25/08/2014
   939                                  ;	cli			; Disable interrupts
   940                                  ;	mov	al, [scounter + 1]
   941                                  ;	and	al, al
   942                                  ;	jnz	hang
   943                                  ;	call	rtc_p
   944                                  ;	jmp     hang
   945                                  
   946                                  
   947                                  	; 27/08/2014
   948                                  	; 20/08/2014
   949                                  printk:
   950                                          ;mov    edi, [scr_row]
   951                                  pkl:
   952 00000636 AC                      	lodsb
   953 00000637 08C0                    	or 	al, al
   954 00000639 7404                    	jz	short pkr
   955 0000063B 66AB                    	stosw
   956 0000063D EBF7                    	jmp	short pkl
   957                                  pkr:
   958 0000063F C3                      	retn
   959                                  
   960                                  ; 25/07/2015
   961                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   962                                  ; 17/02/2015
   963                                  ; 06/02/2015 (unix386.s)
   964                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   965                                  ;
   966                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   967                                  ;
   968                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   969                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   970                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   971                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   972                                  ;									       :
   973                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   974                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   975                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   976                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   977                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   978                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   979                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   980                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   981                                  ;-------------------------------------------------------------------------------
   982                                  ;
   983                                  
   984                                  timer_int:	; IRQ 0
   985                                  ;int_08h:	; Timer
   986                                  	; 14/10/2015
   987                                  	; Here, we are simulating system call entry (for task switch)
   988                                  	; (If multitasking is enabled, 
   989                                  	; 'clock' procedure may jump to 'sysrelease')
   990 00000640 1E                      	push	ds
   991 00000641 06                      	push	es
   992 00000642 0FA0                    	push	fs
   993 00000644 0FA8                    	push	gs
   994 00000646 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   995 00000647 66B91000                	mov     cx, KDATA
   996 0000064B 8ED9                            mov     ds, cx
   997 0000064D 8EC1                            mov     es, cx
   998 0000064F 8EE1                            mov     fs, cx
   999 00000651 8EE9                            mov     gs, cx
  1000                                  	;
  1001 00000653 0F20D9                  	mov	ecx, cr3
  1002 00000656 890D[F9060000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
  1003                                  	;
  1004 0000065C 3B0D[28610000]          	cmp 	ecx, [k_page_dir]
  1005 00000662 741F                    	je	short T3
  1006                                  	;
  1007                                  	; timer interrupt has been occurred while OS is in user mode
  1008 00000664 A3[EC640000]            	mov 	[u.r0], eax
  1009 00000669 89E1                    	mov	ecx, esp
  1010 0000066B 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
  1011 0000066E 890D[E4640000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
  1012 00000674 8925[E8640000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
  1013                                  	;
  1014 0000067A 8B0D[28610000]          	mov	ecx, [k_page_dir]
  1015 00000680 0F22D9                  	mov	cr3, ecx
  1016                                  T3:
  1017 00000683 FB                      	sti				; INTERRUPTS BACK ON
  1018 00000684 66FF05[A4610000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
  1019 0000068B 7507                    	JNZ	short T4		; GO TO TEST_DAY
  1020 0000068D 66FF05[A6610000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
  1021                                  T4:					; TEST_DAY
  1022 00000694 66833D[A6610000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
  1023 0000069C 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1024 0000069E 66813D[A4610000]B0-     	CMP	word [TIMER_LOW],0B0H
  1024 000006A6 00                 
  1025 000006A7 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1026                                  
  1027                                  ;-----	TIMER HAS GONE 24 HOURS
  1028                                  	;;SUB	AX,AX
  1029                                  	;MOV	[TIMER_HIGH],AX
  1030                                  	;MOV	[TIMER_LOW],AX
  1031 000006A9 29C0                    	sub	eax, eax
  1032 000006AB A3[A4610000]            	mov	[TIMER_LH], eax
  1033                                  	;	
  1034 000006B0 C605[A8610000]01        	MOV	byte [TIMER_OFL],1
  1035                                  
  1036                                  ;-----	TEST FOR DISKETTE TIME OUT
  1037                                  
  1038                                  T5:
  1039                                  	; 23/12/2014
  1040 000006B7 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1041                                  					; (9090h) if a floppy disk
  1042                                  					; is detected.
  1043                                  	;mov	al,[CS:MOTOR_COUNT]
  1044 000006B9 A0[AB610000]            	mov	al, [MOTOR_COUNT]
  1045 000006BE FEC8                    	dec	al
  1046                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1047 000006C0 A2[AB610000]            	mov	[MOTOR_COUNT], al
  1048                                  	;mov	[ORG_MOTOR_COUNT], al
  1049 000006C5 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1050 000006C7 B0F0                    	mov 	al,0F0h
  1051                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1052 000006C9 2005[AA610000]          	and	[MOTOR_STATUS], al
  1053                                  	;and	[ORG_MOTOR_STATUS], al
  1054 000006CF B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1055                                  					; bit 2 = enable controller
  1056                                  					;	1 = normal operation
  1057                                  					;	0 = reset	
  1058                                  					; bit 0, 1 = drive select
  1059                                  					; bit 4-7 = motor running bits 
  1060 000006D1 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1061 000006D5 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1062                                  T6:	
  1063                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1064                                  					; TIMER TICK INTERRUPT
  1065                                  	;;inc	word [wait_count] ;;27/02/2015
  1066                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1067                                  	;;;;cli
  1068                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1069 000006D6 FF15[F1060000]          	call	[x_timer] ; 14/05/2015
  1070                                  T7:
  1071                                  	; 14/10/2015
  1072 000006DC B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1073 000006DE FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1074 000006DF E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1075                                  	;
  1076 000006E1 A1[F9060000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1077 000006E6 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1078                                  	;
  1079 000006E9 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1080                                  	;
  1081 000006EA 0FA9                    	pop	gs
  1082 000006EC 0FA1                    	pop	fs
  1083 000006EE 07                      	pop	es
  1084 000006EF 1F                      	pop	ds
  1085 000006F0 CF                      	iretd	; return from interrupt
  1086                                  
  1087                                  
  1088                                  ; ////////////////
  1089                                  
  1090                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1091                                  x_timer:
  1092 000006F1 [FD060000]              	dd 	u_timer			; 14/05/2015
  1093                                  	;dd	clock
  1094                                  
  1095                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1096                                  x_rtci:
  1097 000006F5 [330A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1098                                  
  1099                                  ; 14/10/2015
  1100 000006F9 00000000                cr3reg: dd 0
  1101                                  
  1102                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1103                                  	; 06/02/2015
  1104                                  	; 07/09/2014
  1105                                  	; 21/08/2014
  1106                                  u_timer:
  1107                                  ;timer_int:	; IRQ 0
  1108                                  	; 06/02/2015
  1109                                  	;push	eax
  1110                                  	;push	edx
  1111                                  	;push	ecx
  1112                                  	;push	ebx
  1113                                  	;push	ds
  1114                                  	;push	es
  1115                                  	;mov	eax, KDATA
  1116                                  	;mov	ds, ax
  1117                                  	;mov	es, ax
  1118 000006FD FF05[6C610000]          	inc	dword [tcount]
  1119 00000703 BB[F65C0000]            	mov	ebx, tcountstr + 4
  1120                                  	;mov	ax, [tcount]
  1121                                  	; 24/12/2021
  1122 00000708 A1[6C610000]            	mov	eax, [tcount]
  1123 0000070D B90A000000              	mov	ecx, 10
  1124                                  rp_divtcnt:
  1125 00000712 31D2                    	xor	edx, edx
  1126 00000714 F7F1                    	div	ecx
  1127 00000716 80C230                  	add	dl, 30h
  1128 00000719 8813                    	mov	[ebx], dl
  1129                                  	;or	ax, ax
  1130                                  	; 24/12/2021
  1131 0000071B 09C0                    	or	eax, eax
  1132 0000071D 7403                    	jz	short print_lzero
  1133 0000071F 4B                      	dec	ebx
  1134 00000720 EBF0                    	jmp	short rp_divtcnt
  1135                                  print_lzero:
  1136 00000722 81FB[F25C0000]          	cmp	ebx, tcountstr
  1137 00000728 7606                    	jna	short print_tcount
  1138 0000072A 4B                      	dec	ebx
  1139 0000072B C60330                   	mov	byte [ebx], 30h
  1140 0000072E EBF2                    	jmp	short print_lzero
  1141                                  print_tcount:
  1142 00000730 56                      	push	esi
  1143 00000731 57                      	push	edi
  1144 00000732 BE[CE5C0000]            	mov	esi, timer_msg ; Timer interrupt message
  1145                                  	; 07/09/2014
  1146                                  	;mov	bx, 1	; Video page 1
  1147                                  	; 24/12/2021
  1148 00000737 29DB                    	sub	ebx, ebx
  1149                                  	;inc	bl ; ebx = 1
  1150                                  	; 02/01/2022
  1151 00000739 B306                    	mov	bl, 6	; Video page 6
  1152                                  ptmsg:
  1153 0000073B AC                      	lodsb
  1154 0000073C 08C0                    	or	al, al
  1155 0000073E 740D                    	jz	short ptmsg_ok
  1156 00000740 56                      	push	esi
  1157                                  	;push	bx
  1158                                  	; 24/12/2021
  1159 00000741 53                              push	ebx
  1160 00000742 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1161 00000744 E8530B0000              	call 	write_tty
  1162                                  	;pop	bx
  1163                                  	; 24/12/2021
  1164 00000749 5B                      	pop	ebx
  1165 0000074A 5E                      	pop	esi
  1166 0000074B EBEE                    	jmp	short ptmsg
  1167                                  	;; 27/08/2014
  1168                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1169                                  	;call	printk
  1170                                  	;
  1171                                  ptmsg_ok:
  1172                                  	; 07/09/2014
  1173                                  	;xor	dx, dx		; column 0, row 0
  1174                                  	; 24/12/2021
  1175 0000074D 31D2                    	xor	edx, edx
  1176 0000074F E8520C0000              	call	set_cpos	; set cursor position to 0,0 
  1177                                  	; 23/02/2015
  1178                                  	; 25/08/2014
  1179                                  	;mov	ebx, scounter		; (seconds counter)
  1180                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1181                                  ;	dec	byte [scounter+1]
  1182                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1183                                  ;	jns	short u_timer_retn
  1184                                  	; 26/02/2015
  1185                                  ;	call	rtc_p
  1186                                  ;	mov	ebx, scounter		; (seconds counter)
  1187                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1188                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1189                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1190                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1191                                  ;	mov	byte [ebx], 5
  1192                                  ;	inc	byte [ebx+1] ; 19
  1193                                  ;;timer_eoi:
  1194                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1195                                  ;;	out	20h, al	; 8259 PORT
  1196                                  	;
  1197                                  ;u_timer_retn:  ; 06/02/2015
  1198 00000754 5F                      	pop	edi
  1199 00000755 5E                      	pop	esi
  1200                                  	;pop	es
  1201                                  	;pop	ds
  1202                                  	;pop	ebx
  1203                                  	;pop	ecx
  1204                                  	;pop	edx
  1205                                  	;pop	eax
  1206                                  	;iret
  1207 00000756 C3                      	retn	; 06/02/2015
  1208                                  
  1209                                  	; 28/08/2014
  1210                                  irq0:
  1211 00000757 6A00                            push 	dword 0
  1212 00000759 EB48                    	jmp	short which_irq
  1213                                  irq1:
  1214 0000075B 6A01                            push 	dword 1
  1215 0000075D EB44                    	jmp	short which_irq
  1216                                  irq2:
  1217 0000075F 6A02                            push 	dword 2
  1218 00000761 EB40                    	jmp	short which_irq
  1219                                  irq3:
  1220                                  	; 20/11/2015
  1221                                  	; 24/10/2015
  1222 00000763 2EFF15[CE2F0000]        	call	dword [cs:com2_irq3]
  1223 0000076A 6A03                    	push 	dword 3
  1224 0000076C EB35                    	jmp	short which_irq
  1225                                  irq4:
  1226                                  	; 20/11/2015
  1227                                  	; 24/10/2015
  1228 0000076E 2EFF15[CA2F0000]        	call	dword [cs:com1_irq4]
  1229 00000775 6A04                            push 	dword 4
  1230 00000777 EB2A                    	jmp	short which_irq
  1231                                  irq5:
  1232 00000779 6A05                            push 	dword 5
  1233 0000077B EB26                    	jmp	short which_irq
  1234                                  irq6:
  1235 0000077D 6A06                            push 	dword 6
  1236 0000077F EB22                    	jmp	short which_irq
  1237                                  irq7:
  1238 00000781 6A07                            push 	dword 7
  1239 00000783 EB1E                    	jmp	short which_irq
  1240                                  irq8:
  1241 00000785 6A08                            push 	dword 8
  1242 00000787 EB1A                    	jmp	short which_irq
  1243                                  irq9:
  1244 00000789 6A09                            push 	dword 9
  1245 0000078B EB16                    	jmp	short which_irq
  1246                                  irq10:
  1247 0000078D 6A0A                            push 	dword 10
  1248 0000078F EB12                    	jmp	short which_irq
  1249                                  irq11:
  1250 00000791 6A0B                            push 	dword 11
  1251 00000793 EB0E                    	jmp	short which_irq
  1252                                  irq12:
  1253 00000795 6A0C                            push 	dword 12
  1254 00000797 EB0A                    	jmp	short which_irq
  1255                                  irq13:
  1256 00000799 6A0D                            push 	dword 13
  1257 0000079B EB06                    	jmp	short which_irq
  1258                                  irq14:
  1259 0000079D 6A0E                            push 	dword 14
  1260 0000079F EB02                    	jmp	short which_irq
  1261                                  irq15:
  1262 000007A1 6A0F                            push 	dword 15
  1263                                  	;jmp	short which_irq
  1264                                  
  1265                                  	; 19/10/2015
  1266                                  	; 29/08/2014
  1267                                  	; 21/08/2014
  1268                                  which_irq:
  1269 000007A3 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1270 000007A6 53                      	push	ebx
  1271 000007A7 56                      	push	esi
  1272 000007A8 57                      	push	edi
  1273 000007A9 1E                      	push 	ds
  1274 000007AA 06                      	push 	es
  1275                                  	;
  1276 000007AB 88C3                    	mov	bl, al
  1277                                  	;
  1278 000007AD B810000000              	mov	eax, KDATA
  1279 000007B2 8ED8                    	mov	ds, ax
  1280 000007B4 8EC0                    	mov	es, ax
  1281                                  	; 19/10/2015
  1282 000007B6 FC                      	cld
  1283                                          ; 27/08/2014
  1284 000007B7 8105[7C5C0000]A000-             add     dword [scr_row], 0A0h
  1284 000007BF 0000               
  1285                                  	;
  1286 000007C1 B417                    	mov	ah, 17h	; blue (1) background, 
  1287                                  			; light gray (7) forecolor
  1288 000007C3 8B3D[7C5C0000]                  mov     edi, [scr_row]
  1289 000007C9 B049                    	mov	al, 'I'
  1290 000007CB 66AB                    	stosw
  1291 000007CD B052                    	mov	al, 'R'
  1292 000007CF 66AB                    	stosw
  1293 000007D1 B051                    	mov	al, 'Q'
  1294 000007D3 66AB                    	stosw
  1295 000007D5 B020                    	mov	al, ' '
  1296 000007D7 66AB                    	stosw
  1297 000007D9 88D8                    	mov	al, bl
  1298 000007DB 3C0A                    	cmp	al, 10
  1299 000007DD 7208                    	jb	short iix
  1300 000007DF B031                    	mov	al, '1'
  1301 000007E1 66AB                    	stosw
  1302 000007E3 88D8                    	mov	al, bl
  1303 000007E5 2C0A                    	sub	al, 10
  1304                                  iix:
  1305 000007E7 0430                    	add	al, '0'
  1306 000007E9 66AB                    	stosw
  1307 000007EB B020                    	mov	al, ' '
  1308 000007ED 66AB                    	stosw
  1309 000007EF B021                    	mov	al, '!'
  1310 000007F1 66AB                    	stosw
  1311 000007F3 B020                    	mov	al, ' '
  1312 000007F5 66AB                    	stosw
  1313                                  	; 23/02/2015
  1314 000007F7 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1315                                  	;jna	iiret
  1316                                  	; 02/01/2022
  1317 000007FA 7604                    	jna	short iiz
  1318                                  iiy:
  1319 000007FC B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1320 000007FE E6A0                    	out	0A0h, al ; the 2nd 8259
  1321                                  iiz:
  1322 00000800 E983010000              	jmp     iiret
  1323                                  	;
  1324                                  	; 22/08/2014
  1325                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1326                                  	;out	20h, al	; 8259 PORT
  1327                                  	;
  1328                                  	;pop	es
  1329                                  	;pop	ds
  1330                                  	;pop	edi
  1331                                  	;pop	esi
  1332                                  	;pop	ebx
  1333                                  	;pop 	eax
  1334                                  	;iret
  1335                                  
  1336                                  	; 02/04/2015
  1337                                  	; 25/08/2014
  1338                                  exc0:
  1339 00000805 6A00                            push 	dword 0
  1340 00000807 E990000000                      jmp     cpu_except
  1341                                  exc1:
  1342 0000080C 6A01                            push 	dword 1
  1343 0000080E E989000000                      jmp     cpu_except
  1344                                  exc2:
  1345 00000813 6A02                            push 	dword 2
  1346 00000815 E982000000                      jmp     cpu_except
  1347                                  exc3:
  1348 0000081A 6A03                            push 	dword 3
  1349 0000081C EB7E                            jmp     cpu_except
  1350                                  exc4:
  1351 0000081E 6A04                            push 	dword 4
  1352 00000820 EB7A                            jmp     cpu_except
  1353                                  exc5:
  1354 00000822 6A05                            push 	dword 5
  1355 00000824 EB76                            jmp     cpu_except
  1356                                  exc6:
  1357 00000826 6A06                            push 	dword 6
  1358 00000828 EB72                            jmp     cpu_except
  1359                                  exc7:
  1360 0000082A 6A07                            push 	dword 7
  1361 0000082C EB6E                            jmp     cpu_except
  1362                                  exc8:
  1363                                  	; [esp] = Error code
  1364 0000082E 6A08                            push 	dword 8
  1365 00000830 EB5C                            jmp     cpu_except_en
  1366                                  exc9:
  1367 00000832 6A09                            push 	dword 9
  1368 00000834 EB66                            jmp     cpu_except
  1369                                  exc10:
  1370                                  	; [esp] = Error code
  1371 00000836 6A0A                            push 	dword 10
  1372 00000838 EB54                            jmp     cpu_except_en
  1373                                  exc11:
  1374                                  	; [esp] = Error code
  1375 0000083A 6A0B                            push 	dword 11
  1376 0000083C EB50                            jmp     cpu_except_en
  1377                                  exc12:
  1378                                  	; [esp] = Error code
  1379 0000083E 6A0C                            push 	dword 12
  1380 00000840 EB4C                            jmp     cpu_except_en
  1381                                  exc13:
  1382                                  	; [esp] = Error code
  1383 00000842 6A0D                            push 	dword 13
  1384 00000844 EB48                            jmp     cpu_except_en
  1385                                  exc14:
  1386                                  	; [esp] = Error code
  1387 00000846 6A0E                            push 	dword 14
  1388 00000848 EB44                    	jmp	short cpu_except_en
  1389                                  exc15:
  1390 0000084A 6A0F                            push 	dword 15
  1391 0000084C EB4E                            jmp     cpu_except
  1392                                  exc16:
  1393 0000084E 6A10                            push 	dword 16
  1394 00000850 EB4A                            jmp     cpu_except
  1395                                  exc17:
  1396                                  	; [esp] = Error code
  1397 00000852 6A11                            push 	dword 17
  1398 00000854 EB38                    	jmp	short cpu_except_en
  1399                                  exc18:
  1400 00000856 6A12                            push 	dword 18
  1401 00000858 EB42                    	jmp	short cpu_except
  1402                                  exc19:
  1403 0000085A 6A13                            push 	dword 19
  1404 0000085C EB3E                    	jmp	short cpu_except
  1405                                  exc20:
  1406 0000085E 6A14                            push 	dword 20
  1407 00000860 EB3A                    	jmp	short cpu_except
  1408                                  exc21:
  1409 00000862 6A15                            push 	dword 21
  1410 00000864 EB36                    	jmp	short cpu_except
  1411                                  exc22:
  1412 00000866 6A16                            push 	dword 22
  1413 00000868 EB32                    	jmp	short cpu_except
  1414                                  exc23:
  1415 0000086A 6A17                            push 	dword 23
  1416 0000086C EB2E                    	jmp	short cpu_except
  1417                                  exc24:
  1418 0000086E 6A18                            push 	dword 24
  1419 00000870 EB2A                    	jmp	short cpu_except
  1420                                  exc25:
  1421 00000872 6A19                            push 	dword 25
  1422 00000874 EB26                    	jmp	short cpu_except
  1423                                  exc26:
  1424 00000876 6A1A                            push 	dword 26
  1425 00000878 EB22                    	jmp	short cpu_except
  1426                                  exc27:
  1427 0000087A 6A1B                            push 	dword 27
  1428 0000087C EB1E                    	jmp	short cpu_except
  1429                                  exc28:
  1430 0000087E 6A1C                            push 	dword 28
  1431 00000880 EB1A                    	jmp	short cpu_except
  1432                                  exc29:
  1433 00000882 6A1D                            push 	dword 29
  1434 00000884 EB16                    	jmp	short cpu_except
  1435                                  exc30:
  1436 00000886 6A1E                            push 	dword 30
  1437 00000888 EB04                    	jmp	short cpu_except_en
  1438                                  exc31:
  1439 0000088A 6A1F                            push 	dword 31
  1440 0000088C EB0E                            jmp     short cpu_except
  1441                                  
  1442                                  	; 02/01/2022
  1443                                  	; 19/10/2015
  1444                                  	; 19/09/2015
  1445                                  	; 01/09/2015
  1446                                  	; 28/08/2015
  1447                                  	; 28/08/2014
  1448                                  cpu_except_en:
  1449 0000088E 87442404                	xchg	eax, [esp+4] ; Error code
  1450 00000892 36A3[D4610000]          	mov	[ss:error_code], eax
  1451 00000898 58                      	pop	eax  ; Exception number
  1452 00000899 870424                  	xchg	eax, [esp]
  1453                                  		; eax = eax before exception
  1454                                  		; [esp] -> exception number
  1455                                  		; [esp+4] -> EIP to return
  1456                                  	; 19/10/2015
  1457                                  	; 19/09/2015
  1458                                  	; 01/09/2015
  1459                                  	; 28/08/2015
  1460                                  	; 29/08/2014
  1461                                  	; 28/08/2014
  1462                                  	; 25/08/2014
  1463                                  	; 21/08/2014
  1464                                  cpu_except:	; CPU Exceptions
  1465 0000089C FC                      	cld
  1466 0000089D 870424                  	xchg	eax, [esp] 
  1467                                  		; eax = Exception number
  1468                                  		; [esp] = eax (before exception)
  1469 000008A0 53                      	push	ebx
  1470 000008A1 56                      	push	esi
  1471 000008A2 57                      	push	edi
  1472 000008A3 1E                      	push 	ds
  1473 000008A4 06                      	push 	es
  1474                                  	; 28/08/2015
  1475 000008A5 66BB1000                	mov	bx, KDATA
  1476 000008A9 8EDB                    	mov	ds, bx
  1477 000008AB 8EC3                    	mov	es, bx
  1478 000008AD 0F20DB                  	mov	ebx, cr3
  1479 000008B0 53                      	push	ebx ; (*) page directory
  1480                                  	; 19/10/2015
  1481 000008B1 FC                      	cld
  1482                                  	; 25/03/2015
  1483 000008B2 8B1D[28610000]          	mov	ebx, [k_page_dir]
  1484 000008B8 0F22DB                  	mov	cr3, ebx
  1485                                  	; 28/08/2015
  1486 000008BB 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1487 000008BE 7513                    	jne	short cpu_except_nfp
  1488 000008C0 E8AD1D0000              	call	page_fault_handler
  1489 000008C5 21C0                    	and 	eax, eax
  1490                                  	;jz	iiretp ; 01/09/2015
  1491                                  	; 02/01/2022
  1492 000008C7 7505                    	jnz	short cpu_except_pf
  1493 000008C9 E9B6000000              	jmp	iiretp
  1494                                  cpu_except_pf:
  1495 000008CE B80E000000              	mov	eax, 0Eh ; 14
  1496                                  cpu_except_nfp:
  1497                                  	; 02/04/2015
  1498 000008D3 BB[FD050000]            	mov	ebx, hang
  1499 000008D8 875C241C                	xchg	ebx, [esp+28]
  1500                                  		; EIP (points to instruction which faults)
  1501                                  	  	; New EIP (hang)
  1502 000008DC 891D[D8610000]          	mov	[FaultOffset], ebx
  1503 000008E2 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1504 000008EA 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1505                                  	;
  1506 000008F2 88C4                    	mov	ah, al
  1507 000008F4 240F                    	and	al, 0Fh
  1508 000008F6 3C09                    	cmp	al, 9
  1509 000008F8 7602                    	jna	short h1ok
  1510 000008FA 0407                    	add	al, 'A'-':'
  1511                                  h1ok:
  1512 000008FC D0EC                    	shr	ah, 1
  1513 000008FE D0EC                    	shr	ah, 1
  1514 00000900 D0EC                    	shr	ah, 1
  1515 00000902 D0EC                    	shr	ah, 1
  1516 00000904 80FC09                  	cmp	ah, 9
  1517 00000907 7603                    	jna	short h2ok
  1518 00000909 80C407                  	add	ah, 'A'-':'
  1519                                  h2ok:	
  1520 0000090C 86E0                    	xchg 	ah, al	
  1521 0000090E 66053030                	add	ax, '00'
  1522 00000912 66A3[0A5D0000]          	mov	[excnstr], ax
  1523                                  	;
  1524                                  	; 29/08/2014
  1525 00000918 A1[D8610000]            	mov	eax, [FaultOffset]
  1526 0000091D 51                      	push	ecx
  1527 0000091E 52                      	push	edx
  1528 0000091F 89E3                    	mov	ebx, esp
  1529                                  	; 28/08/2015
  1530 00000921 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1531                                  			  ; to hexadecimal string
  1532                                  	;mov	ecx, 10	    ; divisor to convert
  1533                                  			    ; binary number to decimal string
  1534                                  b2d1:
  1535 00000926 31D2                    	xor	edx, edx
  1536 00000928 F7F1                    	div	ecx
  1537                                  	;push	dx
  1538                                  	; 02/01/2022
  1539 0000092A 52                      	push	edx
  1540 0000092B 39C8                    	cmp	eax, ecx
  1541 0000092D 73F7                    	jnb	short b2d1
  1542 0000092F BF[155D0000]            	mov	edi, EIPstr ; EIP value
  1543                                  			    ; points to instruction which faults
  1544                                  	; 28/08/2015
  1545 00000934 89C2                    	mov	edx, eax
  1546                                  b2d2:
  1547                                  	;add	al, '0'
  1548 00000936 8A82[D8150000]          	mov	al, [edx+hexchrs]
  1549 0000093C AA                      	stosb		    ; write hexadecimal digit to its place
  1550 0000093D 39E3                    	cmp	ebx, esp
  1551 0000093F 7605                    	jna	short b2d3
  1552                                  	; 02/01/2022
  1553 00000941 58                      	pop	eax
  1554                                  	;pop	ax
  1555 00000942 88C2                    	mov	dl, al
  1556 00000944 EBF0                    	jmp	short b2d2
  1557                                  b2d3:
  1558 00000946 B068                    	mov 	al, 'h' ; 28/08/2015
  1559 00000948 AA                      	stosb
  1560 00000949 B020                    	mov	al, 20h	    ; space
  1561 0000094B AA                      	stosb
  1562 0000094C 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1563 0000094E AA                      	stosb
  1564                                  	;
  1565 0000094F 5A                      	pop	edx
  1566 00000950 59                      	pop	ecx
  1567                                  	;
  1568 00000951 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1569                                  			; white (F) forecolor
  1570 00000953 BE[FA5C0000]            	mov	esi, exc_msg ; message offset
  1571                                  	;
  1572 00000958 EB11                    	jmp	short piemsg
  1573                                  	;
  1574                                          ;add    dword [scr_row], 0A0h
  1575                                          ;mov    edi, [scr_row]
  1576                                          ;
  1577                                  	;call 	printk
  1578                                  	;
  1579                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1580                                  	;out	20h, al	; 8259 PORT
  1581                                  	;
  1582                                  	;pop	es
  1583                                  	;pop	ds
  1584                                  	;pop	edi
  1585                                  	;pop	esi
  1586                                  	;pop 	eax
  1587                                  	;iret
  1588                                  	
  1589                                  	; 28/08/2015
  1590                                  	; 23/02/2015
  1591                                  	; 20/08/2014
  1592                                  ignore_int:
  1593 0000095A 50                      	push	eax
  1594 0000095B 53                      	push	ebx ; 23/02/2015
  1595 0000095C 56                      	push	esi
  1596 0000095D 57                      	push	edi
  1597 0000095E 1E                      	push 	ds
  1598 0000095F 06                      	push 	es
  1599                                  	; 28/08/2015
  1600 00000960 0F20D8                  	mov	eax, cr3
  1601 00000963 50                      	push	eax ; (*) page directory
  1602                                  	;
  1603 00000964 B467                    	mov	ah, 67h	; brown (6) background, 
  1604                                  			; light gray (7) forecolor
  1605 00000966 BE[B85C0000]            	mov	esi, int_msg ; message offset
  1606                                  piemsg:
  1607                                          ; 27/08/2014
  1608 0000096B 8105[7C5C0000]A000-             add     dword [scr_row], 0A0h
  1608 00000973 0000               
  1609 00000975 8B3D[7C5C0000]                  mov     edi, [scr_row]
  1610                                          ;
  1611 0000097B E8B6FCFFFF              	call 	printk
  1612                                  	;
  1613                                  	; 23/02/2015
  1614 00000980 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1615 00000982 E6A0                    	out	0A0h, al ; the 2nd 8259
  1616                                  iiretp: ; 01/09/2015
  1617                                  	; 28/08/2015
  1618 00000984 58                      	pop	eax ; (*) page directory
  1619 00000985 0F22D8                  	mov	cr3, eax
  1620                                  	;
  1621                                  iiret:
  1622                                  	; 22/08/2014
  1623 00000988 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1624 0000098A E620                    	out	20h, al	; 8259 PORT
  1625                                  	;
  1626 0000098C 07                      	pop	es
  1627 0000098D 1F                      	pop	ds
  1628 0000098E 5F                      	pop	edi
  1629 0000098F 5E                      	pop	esi
  1630 00000990 5B                      	pop	ebx ; 29/08/2014
  1631 00000991 58                      	pop 	eax
  1632 00000992 CF                      	iretd
  1633                                  
  1634                                  	; 26/02/2022
  1635                                  	; 26/02/2015
  1636                                  	; 07/09/2014
  1637                                  	; 25/08/2014
  1638                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1639                                  	; 22/08/2014
  1640 00000993 50                      	push	eax
  1641 00000994 53                      	push	ebx ; 29/08/2014
  1642 00000995 56                      	push	esi
  1643 00000996 57                      	push	edi
  1644 00000997 1E                      	push 	ds
  1645 00000998 06                      	push 	es
  1646                                  	;
  1647 00000999 B810000000              	mov	eax, KDATA
  1648 0000099E 8ED8                    	mov	ds, ax
  1649 000009A0 8EC0                    	mov	es, ax
  1650                                  	;
  1651                                  	; 25/08/2014
  1652                                  	;call	rtc_p
  1653                                  	; 26/02/2022
  1654 000009A2 FF15[F5060000]          	call	[x_rtci]
  1655                                  	;
  1656                                  	; 22/02/2015 - dsectpm.s
  1657                                  	; [ source: http://wiki.osdev.org/RTC ]
  1658                                  	; read status register C to complete procedure
  1659                                  	;(it is needed to get a next IRQ 8) 
  1660 000009A8 B00C                    	mov	al, 0Ch ; 
  1661 000009AA E670                    	out	70h, al ; select register C
  1662 000009AC 90                      	nop
  1663 000009AD E471                    	in	al, 71h ; just throw away contents
  1664                                  	; 22/02/2015
  1665 000009AF B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1666 000009B1 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1667                                  	;
  1668 000009B3 EBD3                    	jmp	short iiret	
  1669                                  
  1670                                  	; 22/08/2014
  1671                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1672                                  	; (INT 1Ah)
  1673                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1674                                  time_of_day:
  1675 000009B5 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1676 000009BA 726F                            jc      short rtc_retn 
  1677 000009BC B000                    	mov	al, CMOS_SECONDS
  1678 000009BE E847010000              	call	CMOS_READ
  1679 000009C3 A2[9C610000]            	mov	[time_seconds], al 
  1680 000009C8 B002                    	mov	al, CMOS_MINUTES
  1681 000009CA E83B010000              	call	CMOS_READ
  1682 000009CF A2[9D610000]            	mov	[time_minutes], al 
  1683 000009D4 B004                    	mov	al, CMOS_HOURS
  1684 000009D6 E82F010000              	call	CMOS_READ
  1685 000009DB A2[9E610000]                    mov     [time_hours], al
  1686 000009E0 B006                    	mov	al, CMOS_DAY_WEEK 
  1687 000009E2 E823010000              	call	CMOS_READ
  1688 000009E7 A2[9F610000]            	mov	[date_wday], al
  1689 000009EC B007                     	mov	al, CMOS_DAY_MONTH
  1690 000009EE E817010000              	call	CMOS_READ
  1691 000009F3 A2[A0610000]            	mov	[date_day], al
  1692 000009F8 B008                    	mov	al, CMOS_MONTH
  1693 000009FA E80B010000              	call	CMOS_READ
  1694 000009FF A2[A1610000]            	mov	[date_month], al
  1695 00000A04 B009                    	mov	al, CMOS_YEAR
  1696 00000A06 E8FF000000              	call	CMOS_READ
  1697 00000A0B A2[A2610000]            	mov	[date_year], al
  1698 00000A10 B032                    	mov	al, CMOS_CENTURY
  1699 00000A12 E8F3000000              	call	CMOS_READ
  1700 00000A17 A2[A3610000]            	mov	[date_century], al
  1701                                  	;
  1702 00000A1C B000                    	mov	al, CMOS_SECONDS
  1703 00000A1E E8E7000000              	call 	CMOS_READ
  1704 00000A23 3A05[9C610000]          	cmp	al, [time_seconds]
  1705 00000A29 758A                    	jne	short time_of_day
  1706                                  
  1707                                  rtc_retn:
  1708 00000A2B C3                      	retn
  1709                                  
  1710                                  rtci_default:
  1711                                  	; 26/02/2022 (Temporary!)
  1712                                  	; (default real time clock handler in multitasking mode)
  1713                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1714 00000A2C FF05[E0610000]          	inc	dword [rtc_ticks] ; real time clock counter
  1715                                  			; (not used in anywhere of kernel for now!)
  1716 00000A32 C3                      	retn
  1717                                  
  1718                                  rtc_p:	
  1719                                  	; 07/09/2014
  1720                                  	; 29/08/2014
  1721                                  	; 27/08/2014
  1722                                  	; 25/08/2014
  1723                                   	; Print Real Time Clock content
  1724                                  	;
  1725                                  	;
  1726 00000A33 E87DFFFFFF              	call	time_of_day
  1727 00000A38 72F1                    	jc	short rtc_retn
  1728                                  	;
  1729 00000A3A 3A05[6C5D0000]          	cmp	al, [ptime_seconds]
  1730 00000A40 74E9                            je      short rtc_retn ; 29/08/2014
  1731                                  	;
  1732 00000A42 A2[6C5D0000]            	mov	[ptime_seconds], al
  1733                                  	;
  1734 00000A47 A0[A3610000]            	mov	al, [date_century]
  1735 00000A4C E8EA000000              	call	bcd_to_ascii
  1736 00000A51 66A3[395D0000]          	mov	[datestr+6], ax
  1737 00000A57 A0[A2610000]            	mov	al, [date_year]
  1738 00000A5C E8DA000000              	call	bcd_to_ascii
  1739 00000A61 66A3[3B5D0000]          	mov	[datestr+8], ax
  1740 00000A67 A0[A1610000]            	mov	al, [date_month]
  1741 00000A6C E8CA000000              	call	bcd_to_ascii
  1742 00000A71 66A3[365D0000]          	mov	[datestr+3], ax
  1743 00000A77 A0[A0610000]            	mov	al, [date_day]
  1744 00000A7C E8BA000000              	call	bcd_to_ascii
  1745 00000A81 66A3[335D0000]          	mov	[datestr], ax
  1746                                  	;
  1747 00000A87 0FB61D[9F610000]        	movzx	ebx, byte [date_wday]
  1748 00000A8E C0E302                  	shl 	bl, 2
  1749 00000A91 81C3[4C5D0000]          	add	ebx, daytmp
  1750 00000A97 8B03                    	mov	eax, [ebx]
  1751 00000A99 A3[3E5D0000]            	mov	[daystr], eax
  1752                                  	;
  1753 00000A9E A0[9E610000]            	mov	al, [time_hours]
  1754 00000AA3 E893000000              	call	bcd_to_ascii
  1755 00000AA8 66A3[425D0000]          	mov	[timestr], ax
  1756 00000AAE A0[9D610000]            	mov	al, [time_minutes]
  1757 00000AB3 E883000000              	call	bcd_to_ascii
  1758 00000AB8 66A3[455D0000]          	mov	[timestr+3], ax
  1759 00000ABE A0[9C610000]            	mov	al, [time_seconds]
  1760 00000AC3 E873000000              	call	bcd_to_ascii
  1761 00000AC8 66A3[485D0000]          	mov	[timestr+6], ax
  1762                                  	;		
  1763 00000ACE BE[215D0000]            	mov	esi, rtc_msg ; message offset
  1764                                  	; 23/02/2015
  1765 00000AD3 52                      	push	edx
  1766 00000AD4 51                      	push	ecx
  1767                                  	; 07/09/2014
  1768                                  	;mov	bx, 2	; Video page 2
  1769                                  	; 02/01/2022
  1770 00000AD5 29DB                    	sub	ebx, ebx
  1771 00000AD7 B307                    	mov	bl, 7	; Video page 7 
  1772                                  prtmsg:
  1773 00000AD9 AC                      	lodsb
  1774 00000ADA 08C0                    	or	al, al
  1775 00000ADC 740D                    	jz	short prtmsg_ok
  1776 00000ADE 56                      	push	esi
  1777                                  	; 02/01/2022
  1778 00000ADF 53                      	push	ebx
  1779                                  	;push	bx
  1780 00000AE0 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1781                                  			; white (F) forecolor
  1782 00000AE2 E8B5070000              	call 	write_tty
  1783                                  	;pop	bx
  1784                                  	; 02/01/2022
  1785 00000AE7 5B                      	pop	ebx
  1786 00000AE8 5E                      	pop	esi
  1787 00000AE9 EBEE                    	jmp	short prtmsg
  1788                                  	;
  1789                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1790                                  	;call	printk
  1791                                  prtmsg_ok:
  1792                                  	; 07/09/2014
  1793                                  	;xor	dx, dx		; column 0, row 0
  1794                                  	; 02/01/2022
  1795 00000AEB 31D2                    	xor	edx, edx
  1796 00000AED E8B4080000              	call	set_cpos	; set curspor position to 0,0 
  1797                                  	; 23/02/2015
  1798 00000AF2 59                      	pop	ecx
  1799 00000AF3 5A                      	pop	edx
  1800 00000AF4 C3                      	retn
  1801                                  
  1802                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1803                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1804                                  default_irq7:
  1805                                  	; 24/12/2021
  1806                                  	;push	ax
  1807 00000AF5 50                      	push	eax
  1808 00000AF6 B00B                    	mov	al, 0Bh  ; In-Service register
  1809 00000AF8 E620                    	out	20h, al
  1810 00000AFA EB00                            jmp short $+2
  1811 00000AFC EB00                    	jmp short $+2
  1812 00000AFE E420                    	in	al, 20h
  1813 00000B00 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1814 00000B02 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1815 00000B04 B020                            mov     al, 20h ; EOI
  1816 00000B06 E620                    	out	20h, al 
  1817                                  irq7_iret:
  1818                                  	;pop	ax
  1819                                  	; 24/12/2021
  1820 00000B08 58                      	pop	eax
  1821 00000B09 CF                      	iretd	
  1822                                  	
  1823                                  	; 24/12/2021
  1824                                  	; 22/08/2014
  1825                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1826                                  CMOS_READ:
  1827 00000B0A 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1828 00000B0B D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1829 00000B0D F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1830 00000B0E D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1831 00000B10 FA                      	cli		; DISABLE INTERRUPTS
  1832 00000B11 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1833 00000B13 90                      	nop		; I/O DELAY
  1834 00000B14 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1835                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1836                                  	; 24/12/2021
  1837 00000B16 50                      	push	eax
  1838                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1839                                  		     ; ----- 10/06/85 (test4.asm)
  1840 00000B17 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1841                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1842 00000B19 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1843 00000B1B E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1844                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1845                                  	; 24/12/2021
  1846 00000B1D 58                      	pop	eax
  1847 00000B1E 9D                      	popf	
  1848 00000B1F C3                      	retn		; RETURN WITH FLAGS RESTORED
  1849                                  
  1850                                  	; 22/08/2014
  1851                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1852                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1853 00000B20 51                      	push	ecx
  1854 00000B21 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1855                                  		; mov cx, 800	
  1856                                  UPD_10:
  1857 00000B26 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1858 00000B28 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1859 00000B29 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1860 00000B2E A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1861 00000B30 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1862 00000B32 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1863 00000B33 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1864 00000B35 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1865                                  		; xor ax, ax
  1866 00000B37 F9                      	stc				; SET CARRY FOR ERROR
  1867                                  UPD_90:
  1868 00000B38 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1869 00000B39 FA                      	cli				; INTERRUPTS OFF DURING SET
  1870 00000B3A C3                      	retn				; RETURN WITH CY FLAG SET
  1871                                  
  1872                                  bcd_to_ascii:
  1873                                  	; 25/08/2014
  1874                                  	; INPUT ->
  1875                                  	;	al = Packed BCD number
  1876                                  	; OUTPUT ->
  1877                                  	;	ax  = ASCII word/number
  1878                                  	;
  1879                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1880                                  	;
  1881 00000B3B D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1882                                  					; AH = AL / 10h
  1883                                  					; AL = AL MOD 10h
  1884 00000B3D 660D3030                	or ax,'00'                      ; Make it ASCII based
  1885                                  
  1886 00000B41 86E0                            xchg ah, al 
  1887                                  	
  1888 00000B43 C3                      	retn	
  1889                                  	
  1890                                  
  1891                                  %include 'keyboard.inc' ; 07/03/2015
  1892                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - KEYBOARD.INC
  1893                              <1> ; Last Modification: 24/07/2022
  1894                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1895                              <1> ;
  1896                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1897                              <1> 
  1898                              <1> ; 24/07/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.6) 
  1899                              <1> ; 24/07/2022 (Retro UNIX 386 v1, Kernel v0.2.0.22)
  1900                              <1> ; 23/02/2022
  1901                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1902                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1903                              <1> ; 30/06/2015
  1904                              <1> ; 11/03/2015
  1905                              <1> ; 28/02/2015
  1906                              <1> ; 25/02/2015
  1907                              <1> ; 20/02/2015
  1908                              <1> ; 18/02/2015
  1909                              <1> ; 03/12/2014
  1910                              <1> ; 07/09/2014
  1911                              <1> ; KEYBOARD INTERRUPT HANDLER
  1912                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1913                              <1> 
  1914                              <1> ;getch:
  1915                              <1> ;	; 18/02/2015
  1916                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1917                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1918                              <1> ;	; routine, later... (multi tasking ability)
  1919                              <1> ;	; 28/02/2015
  1920                              <1> ;	sti	; enable interrupts
  1921                              <1> ;	;
  1922                              <1> ;	;push	esi
  1923                              <1> ;	;push	ebx
  1924                              <1> ;	;xor	ebx, ebx
  1925                              <1> ;	;mov	bl, [ptty]  ; active_page
  1926                              <1> ;	;mov	esi, ebx
  1927                              <1> ;	;shl 	si, 1
  1928                              <1> ;	;add	esi, ttychr
  1929                              <1> ;getch_1:
  1930                              <1> ;	;mov	ax, [esi]
  1931                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1932                              <1> ;	and	ax, ax
  1933                              <1> ;	jz	short getch_2
  1934                              <1> ;	mov	word [ttychr], 0
  1935                              <1> ;	;mov	word [esi], 0
  1936                              <1> ;	;pop	ebx
  1937                              <1> ;	;pop	esi
  1938                              <1> ;	retn
  1939                              <1> ;getch_2:
  1940                              <1> ;	hlt	; not proper for multi tasking!
  1941                              <1> ;		; (temporary halt for now)
  1942                              <1> ;		; 'sleep' on tty 
  1943                              <1> ;		; will (must) be located here		
  1944                              <1> ;	nop
  1945                              <1> ;	jmp	short getch_1
  1946                              <1> 
  1947                              <1> keyb_int:
  1948                              <1> 	; 24/07/2022
  1949                              <1> 	; 23/02/2022
  1950                              <1> 	; 30/06/2015
  1951                              <1> 	; 25/02/2015
  1952                              <1> 	; 20/02/2015
  1953                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1954                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1955                              <1> 	; 30/06/2014
  1956                              <1> 	; 10/05/2013	
  1957                              <1>       	; Retro Unix 8086 v1 feature only!
  1958                              <1> 	; 03/03/2014
  1959                              <1> 	
  1960 00000B44 1E                  <1> 	push	ds
  1961 00000B45 53                  <1> 	push	ebx
  1962 00000B46 50                  <1> 	push	eax
  1963                              <1> 	;
  1964                              <1> 	; 23/02/2022
  1965 00000B47 9C                  <1> 	pushfd
  1966 00000B48 0E                  <1> 	push	cs
  1967                              <1> 	;mov	ax, KDATA
  1968 00000B49 31C0                <1> 	xor	eax, eax
  1969 00000B4B B010                <1> 	mov	al, KDATA
  1970 00000B4D 8ED8                <1> 	mov	ds, ax
  1971                              <1> 	;
  1972                              <1> 	;pushfd
  1973                              <1> 	;push	cs
  1974 00000B4F E80A010000          <1> 	call	kb_int   ; int_09h
  1975                              <1> 	;
  1976                              <1> 	;mov	ah, 11h	 ; 03/12/2014	
  1977 00000B54 B401                <1> 	mov	ah, 1 ; 24/07/2022
  1978                              <1> 	;call	getc
  1979 00000B56 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1980 00000B5B 744E                <1> 	jz	short keyb_int4
  1981                              <1> 	;
  1982                              <1> 	;mov	ah, 10h	 ; 03/12/2014
  1983 00000B5D B400                <1> 	mov	ah, 0 ; 24/07/2022
  1984                              <1> 	;call	getc
  1985 00000B5F E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1986                              <1> 	;
  1987                              <1> 	; 20/02/2015
  1988 00000B64 0FB61D[56610000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1989                              <1> 	;
  1990 00000B6B 20C0                <1> 	and 	al, al
  1991 00000B6D 751D                <1> 	jnz	short keyb_int1
  1992                              <1> 	;
  1993 00000B6F 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1994 00000B72 7218                <1> 	jb	short keyb_int1
  1995 00000B74 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1996 00000B77 7713                <1> 	ja	short keyb_int1
  1997                              <1> 	;
  1998 00000B79 88D8                <1> 	mov	al, bl
  1999 00000B7B 0468                <1> 	add	al, 68h
  2000 00000B7D 38E0                <1> 	cmp	al, ah
  2001 00000B7F 7409                <1> 	je	short keyb_int0
  2002 00000B81 88E0                <1> 	mov	al, ah
  2003 00000B83 2C68                <1> 	sub	al, 68h
  2004 00000B85 E831090000          <1> 	call	tty_sw
  2005                              <1> 	;movzx	ebx, [ptty]  ; active_page
  2006                              <1> keyb_int0: ; 30/06/2015
  2007                              <1> 	;xor	ax, ax
  2008                              <1> 	; 23/02/2022
  2009 00000B8A 31C0                <1> 	xor	eax, eax
  2010                              <1> keyb_int1:
  2011 00000B8C D0E3                <1> 	shl	bl, 1
  2012 00000B8E 81C3[58610000]      <1> 	add	ebx, ttychr
  2013                              <1> 	;
  2014                              <1> 	;23/02/2022
  2015 00000B94 09C0                <1> 	or	eax, eax
  2016                              <1> 	;or	ax, ax
  2017 00000B96 7406                <1> 	jz	short keyb_int2
  2018                              <1> 	;
  2019 00000B98 66833B00            <1> 	cmp 	word [ebx], 0
  2020 00000B9C 7703                <1>         ja      short keyb_int3 
  2021                              <1> keyb_int2:
  2022 00000B9E 668903              <1>         mov	[ebx], ax  ; Save ascii code
  2023                              <1> 			   ; and scan code of the character
  2024                              <1> 			   ; for current tty (or last tty
  2025                              <1> 			   ; just before tty switch).
  2026                              <1> keyb_int3:
  2027 00000BA1 A0[56610000]        <1>         mov     al, [ptty]
  2028 00000BA6 E82D3A0000          <1> 	call	wakeup
  2029                              <1> 	;
  2030                              <1> keyb_int4:
  2031 00000BAB 58                  <1> 	pop	eax
  2032 00000BAC 5B                  <1> 	pop	ebx
  2033 00000BAD 1F                  <1> 	pop	ds
  2034 00000BAE CF                  <1> 	iret
  2035                              <1> 
  2036                              <1> ; 18/02/2015
  2037                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2038                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2039                              <1> ; scancode and ascii code of the character 
  2040                              <1> ; in the tty input (ttychr) buffer. 
  2041                              <1> ; Test procedures must call 'getch' for tty input
  2042                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2043                              <1> ; due to infinite (key press) waiting loop.
  2044                              <1> ; 
  2045                              <1> ; 03/12/2014
  2046                              <1> ; 26/08/2014
  2047                              <1> ; KEYBOARD I/O
  2048                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2049                              <1> 
  2050                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2051                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2052                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2053                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2054                              <1> 
  2055                              <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2056                              <1> ;int_16h: ; 30/06/2015
  2057                              <1> ;;getc:
  2058                              <1> ;	pushfd	; 28/08/2014
  2059                              <1> ;	push 	cs
  2060                              <1> ;	call 	getc_int
  2061                              <1> ;	retn
  2062                              <1> 
  2063                              <1> 	; 24/07/2022
  2064                              <1> %if 0
  2065                              <1> ; 24/12/2021
  2066                              <1> 
  2067                              <1> 	;-----	SHIFT STATUS
  2068                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2069                              <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2070                              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2071                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2072                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2073                              <1>         shl	ah, 5
  2074                              <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2075                              <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2076                              <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2077                              <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2078                              <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2079                              <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2080                              <1> _K3:
  2081                              <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2082                              <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2083                              <1> 
  2084                              <1> %endif
  2085                              <1> 
  2086                              <1> int_16h:
  2087                              <1> 	; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2088                              <1> 	; 24/07/2022 - (near call return instead of interrupt return)
  2089                              <1> 	
  2090                              <1> 	; INPUT:
  2091                              <1> 	;	AL = Function (0 or 1)
  2092                              <1> 	;	     0 = Read Character
  2093                              <1> 	;	     1 = Get Keyboard Buffer Status
  2094                              <1> 	; OUTPUT:
  2095                              <1> 	;	Function 0 - AX = ASCII (AL) and SCAN CODE (AH)
  2096                              <1> 	;			  of the character (enterrd from the keyboard) 
  2097                              <1> 	;	Function 1 - If ZF = 0
  2098                              <1> 	;			AX = ASCII (AL) and SCAN CODE (AH) of the character
  2099                              <1> 	;			(which is waiting in keyboard buffer)
  2100                              <1> 	;		     If ZF = 1
  2101                              <1> 	;			there is not a character in the keyboard buffer
  2102                              <1> 	;
  2103                              <1> 	; Modified registers: eax, ebx
  2104                              <1> 	
  2105                              <1> getc_int:
  2106                              <1> 	; 24/07/2022 (Retro UNIX 386 v1.1 - Kernel v0.2.1.6)
  2107                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2108                              <1> 	; 28/02/2015
  2109                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2110                              <1> 	;	      instead of pc-at bios - 1985-)
  2111                              <1> 	; 28/08/2014 (_k1d)
  2112                              <1> 	; 30/06/2014
  2113                              <1> 	; 03/03/2014
  2114                              <1> 	; 28/02/2014
  2115                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2116                              <1> 	; rombios source code (21/04/1986)
  2117                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2118                              <1> 	;
  2119                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2120                              <1> 	;
  2121                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2122                              <1> 	; KEYBOARD I/O								      :
  2123                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2124                              <1> 	; INPUT									      :
  2125                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2126                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2127                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2128                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2129                              <1> 	;-----------------------------------------------------------------------------:
  2130                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2131                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2132                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2133                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2134                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2135                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2136                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2137                              <1> 	;-----------------------------------------------------------------------------:	
  2138                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2139                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2140                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2141                              <1> 	;-----------------------------------------------------------------------------:	
  2142                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2143                              <1> 	;	      (AL) = 05H                                                      :
  2144                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2145                              <1> 	;		       							      :
  2146                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2147                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2148                              <1> 	;                     --------------------------------------------            :
  2149                              <1> 	;			00H        30.0        10H        7.5                 :
  2150                              <1> 	;			01H        26.7        11H        6.7                 :
  2151                              <1> 	;			02H        24.0        12H        6.0                 :
  2152                              <1> 	;			03H        21.8        13H        5.5                 :
  2153                              <1> 	;			04H        20.0        14H        5.0                 :
  2154                              <1> 	;			05H        18.5        15H        4.6                 :
  2155                              <1> 	;			06H        17.1        16H        4.3                 :
  2156                              <1> 	;			07H        16.0        17H        4.0                 :
  2157                              <1> 	;			08H        15.0        18H        3.7                 :
  2158                              <1> 	;			09H        13.3        19H        3.3                 :
  2159                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2160                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2161                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2162                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2163                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2164                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2165                              <1> 	;									      :
  2166                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2167                              <1> 	;		       							      :
  2168                              <1> 	;                     REGISTER     DELAY                                      :
  2169                              <1> 	;                      VALUE       VALUE                                      :
  2170                              <1> 	;                     ------------------                                      :
  2171                              <1> 	;			00H        250 ms                                     :
  2172                              <1> 	;			01H        500 ms                                     :
  2173                              <1> 	;			02H        750 ms                                     :
  2174                              <1> 	;			03H       1000 ms                                     :
  2175                              <1> 	;-----------------------------------------------------------------------------:
  2176                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2177                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2178                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2179                              <1> 	;		           (CH) = SCAN CODE                                   :
  2180                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2181                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2182                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2183                              <1> 	;-----------------------------------------------------------------------------:		
  2184                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2185                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2186                              <1> 	;-----------------------------------------------------------------------------:
  2187                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2188                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2189                              <1> 	;-----------------------------------------------------------------------------:	
  2190                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2191                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2192                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2193                              <1> 	; OUTPUT					                              :
  2194                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2195                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2196                              <1> 	;------------------------------------------------------------------------------
  2197                              <1> 	
  2198 00000BAF FB                  <1> 	sti				; INTERRUPTS BACK ON
  2199                              <1> 
  2200                              <1> 	; 24/07/2022
  2201                              <1> 	;push	ds			; SAVE CURRENT DS
  2202                              <1> 	;push	ebx			; SAVE BX TEMPORARILY
  2203                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2204                              <1>         ;mov	bx, KDATA 
  2205                              <1> 	;mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2206                              <1> 
  2207                              <1> 	;or	ah, ah			; CHECK FOR (AH)= 00H
  2208                              <1> 	;jz	short _K1		; ASCII_READ
  2209                              <1> 	;dec	ah                      ; CHECK FOR (AH)= 01H
  2210                              <1> 	;jz	short _K2               ; ASCII_STATUS
  2211                              <1> 	;dec	ah			; CHECK FOR (AH)= 02H
  2212                              <1> 	;jz	short _K3               ; SHIFT STATUS
  2213                              <1> 	;dec	ah			; CHECK FOR (AH)= 03H	
  2214                              <1> 	;jz	short _K300             ; SET TYPAMATIC RATE/DELAY
  2215                              <1> 	;sub	ah, 2			; CHECK FOR (AH)= 05H	
  2216                              <1> 	;jz	short _K500             ; KEYBOARD WRITE         
  2217                              <1> ;_KIO1:	
  2218                              <1> 	;sub	ah, 11			; AH =  10H
  2219                              <1> 	;jz	short _K1E		; EXTENDED ASCII READ
  2220                              <1> 	;dec	ah			; CHECK FOR (AH)= 11H
  2221                              <1> 	;jz	short _K2E		; EXTENDED_ASCII_STATUS
  2222                              <1> 	;dec	ah			; CHECK FOR (AH)= 12H
  2223                              <1> 	;jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2224                              <1> 
  2225                              <1> ;_KIO_EXIT:
  2226                              <1> 	;pop	ecx			; RECOVER REGISTER
  2227                              <1> 	;pop	ebx			; RECOVER REGISTER
  2228                              <1> 	; 24/07/2022
  2229                              <1> 	;retn
  2230                              <1> 	;pop	ds			; RECOVER SEGMENT
  2231                              <1> 	;iretd				; INVALID COMMAND, EXIT
  2232                              <1> 
  2233 00000BB0 08E4                <1> 	or	ah, ah
  2234 00000BB2 7507                <1> 	jnz	short _K2
  2235                              <1> 
  2236                              <1> 	;-----	ASCII CHARACTER
  2237                              <1> _K1:
  2238                              <1> _K1E:	
  2239 00000BB4 E81C000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2240                              <1> 	;call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2241                              <1> 	;;jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2242                              <1> 	; 24/07/2022
  2243                              <1> 	;retn
  2244 00000BB9 EB0F                <1> 	jmp	short _KIO_E_XLAT
  2245                              <1> ;_K1:	
  2246                              <1> 	;call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2247                              <1> 	;call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2248                              <1> 	;jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2249                              <1> ;_K1A:
  2250                              <1> 	;jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2251                              <1> 	; 24/07/2022
  2252                              <1> 	;retn
  2253                              <1> 
  2254                              <1> 	;-----	ASCII STATUS
  2255                              <1> _K2:
  2256                              <1> _K2E:	
  2257 00000BBB E860000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2258 00000BC0 7407                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2259 00000BC2 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2260 00000BC3 E802000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2261                              <1> 	;jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2262                              <1> 	; 24/07/2022
  2263 00000BC8 9D                  <1> 	popf
  2264                              <1> _K2B:
  2265 00000BC9 C3                  <1> 	retn
  2266                              <1> ;_K2:	
  2267                              <1> 	;call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2268                              <1> 	;jz	short _K2B		; RETURN IF BUFFER EMPTY
  2269                              <1> 	;pushf				; SAVE ZF FROM TEST
  2270                              <1> 	;call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2271                              <1> 	;jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2272                              <1> 	;popf				; INVALID CODE FOR THIS TYPE OF CALL
  2273                              <1> 	;call	_K1S			; THROW THE CHARACTER AWAY
  2274                              <1> 	;jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2275                              <1> ;_K2A:
  2276                              <1> 	;popf				; RESTORE ZF FROM TEST
  2277                              <1> ;_K2B:
  2278                              <1> 	;;pop	ecx			; RECOVER REGISTER
  2279                              <1> 	;pop	ebx			; RECOVER REGISTER
  2280                              <1> 	;pop	ds			; RECOVER SEGMENT
  2281                              <1> 	;retf	4			; THROW AWAY (E)FLAGS
  2282                              <1> 
  2283                              <1> ; 24/12/2021
  2284                              <1> ;	;-----	SHIFT STATUS
  2285                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2286                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2287                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2288                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2289                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2290                              <1> ;       shl	ah, 5
  2291                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2292                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2293                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2294                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2295                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2296                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2297                              <1> ;_K3:
  2298                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2299                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2300                              <1> 
  2301                              <1> 	; 24/07/2022
  2302                              <1> %if 0
  2303                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2304                              <1> _K300:
  2305                              <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2306                              <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2307                              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2308                              <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2309                              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2310                              <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2311                              <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2312                              <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2313                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2314                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2315                              <1> 	shl	bh, 5
  2316                              <1> 	mov	al, bl			; PUT IN RATE
  2317                              <1> 	or	al, bh			; AND DELAY
  2318                              <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2319                              <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2320                              <1> 
  2321                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2322                              <1> _K500:
  2323                              <1> 	push	esi			; SAVE SI (esi)
  2324                              <1> 	cli				; 
  2325                              <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2326                              <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2327                              <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2328                              <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2329                              <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2330                              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2331                              <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2332                              <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2333                              <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2334                              <1> _K502:
  2335                              <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2336                              <1> _K504:
  2337                              <1> 	sti				
  2338                              <1> 	pop	esi			; RECOVER SI (esi)
  2339                              <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2340                              <1> %endif
  2341                              <1> 
  2342                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2343                              <1> _KIO_E_XLAT:
  2344 00000BCA 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2345 00000BCC 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2346 00000BCE 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2347 00000BD0 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2348 00000BD2 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2349                              <1> _KIO_E_RET:				
  2350 00000BD4 C3                  <1> 	retn				; GO BACK
  2351                              <1> 
  2352                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2353                              <1> _K1S:
  2354 00000BD5 FA                  <1> 	cli	; 03/12/2014
  2355 00000BD6 8B1D[905B0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2356 00000BDC 3B1D[945B0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2357                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2358 00000BE2 750F                <1> 	jne	short _k1x ; 03/12/2014
  2359                              <1> 	;
  2360                              <1> 	; 03/12/2014
  2361                              <1> 	; 28/08/2014
  2362                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2363                              <1> 	;;mov	ax, 9002h		; MOVE IN WAIT CODE & TYPE
  2364                              <1> 	;;int	15h			; PERFORM OTHER FUNCTION
  2365                              <1> _K1T:                                   ; ASCII READ
  2366 00000BE4 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2367 00000BE5 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2368                              <1> _K1U:	
  2369 00000BE6 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2370 00000BE7 8B1D[905B0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2371 00000BED 3B1D[945B0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2372                              <1> _k1x:
  2373 00000BF3 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2374 00000BF4 9C                  <1> 	pushf				; SAVE FLAGS
  2375 00000BF5 E895060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2376 00000BFA 8A1D[855B0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2377 00000C00 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2378 00000C02 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2379 00000C05 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2380 00000C07 E82F060000          <1> 	call	SND_LED1
  2381 00000C0C FA                  <1> 	cli				; DISABLE INTERRUPTS
  2382                              <1> _K1V:
  2383 00000C0D 9D                  <1> 	popf				; RESTORE FLAGS
  2384 00000C0E 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2385 00000C0F 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2386                              <1> 	;
  2387 00000C11 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2388 00000C14 E834000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2389 00000C19 891D[905B0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2390 00000C1F C3                  <1> 	retn				; RETURN
  2391                              <1> 
  2392                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2393                              <1> _K2S:
  2394 00000C20 FA                  <1> 	cli				; INTERRUPTS OFF
  2395 00000C21 8B1D[905B0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2396 00000C27 3B1D[945B0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2397 00000C2D 668B03              <1> 	mov	ax, [ebx]
  2398 00000C30 9C                  <1> 	pushf				; SAVE FLAGS
  2399                              <1> 	;push	ax			; SAVE CODE
  2400                              <1> 	; 24/12/2021
  2401 00000C31 50                  <1> 	push	eax
  2402 00000C32 E858060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2403 00000C37 8A1D[855B0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2404 00000C3D 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2405 00000C3F 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2406 00000C42 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2407 00000C44 E8DB050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2408                              <1> _K2T:
  2409                              <1> 	;pop	ax			; RESTORE CODE
  2410                              <1> 	; 24/12/2021
  2411 00000C49 58                  <1> 	pop	eax
  2412 00000C4A 9D                  <1> 	popf				; RESTORE FLAGS
  2413 00000C4B FB                  <1> 	sti				; INTERRUPTS BACK ON
  2414 00000C4C C3                  <1> 	retn				; RETURN
  2415                              <1> 
  2416                              <1> 	; 24/07/2022
  2417                              <1> %if 0
  2418                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2419                              <1> _KIO_S_XLAT:
  2420                              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2421                              <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2422                              <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2423                              <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2424                              <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2425                              <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2426                              <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2427                              <1> _kio_ret: ; 03/12/2014
  2428                              <1> 	clc
  2429                              <1> 	retn
  2430                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2431                              <1> _KIO_S1:				
  2432                              <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2433                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2434                              <1> 	retn
  2435                              <1> _KIO_S2:		
  2436                              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2437                              <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2438                              <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2439                              <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2440                              <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2441                              <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2442                              <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2443                              <1> _KIO_S3:
  2444                              <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2445                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2446                              <1> 	jne	short _kio_ret
  2447                              <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2448                              <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2449                              <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2450                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2451                              <1> _KIO_USE:
  2452                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2453                              <1> 	retn				; RETURN	
  2454                              <1> _KIO_DIS:
  2455                              <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2456                              <1> 	retn				; RETURN
  2457                              <1> 
  2458                              <1> %endif
  2459                              <1> 
  2460                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2461                              <1> _K4:    
  2462 00000C4D 43                  <1> 	inc     ebx
  2463 00000C4E 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2464 00000C4F 3B1D[8C5B0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2465                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2466 00000C55 7206                <1> 	jb	short _K5
  2467 00000C57 8B1D[885B0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2468                              <1> _K5:
  2469 00000C5D C3                  <1> 	retn
  2470                              <1> 
  2471                              <1> ; 20/02/2015
  2472                              <1> ; 05/12/2014
  2473                              <1> ; 26/08/2014
  2474                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2475                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2476                              <1> ;
  2477                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2478                              <1> ; rombios source code (06/10/1985)
  2479                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2480                              <1> 
  2481                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2482                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2483                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2484                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2485                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2486                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2487                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2488                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2489                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2490                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2491                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2492                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2493                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2494                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2495                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2496                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2497                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2498                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2499                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2500                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2501                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2502                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2503                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2504                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2505                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2506                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2507                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2508                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2509                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2510                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2511                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2512                              <1> F11_M		equ	87		; F11 KEY MAKE
  2513                              <1> F12_M		equ	88		; F12 KEY MAKE
  2514                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2515                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2516                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2517                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2518                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2519                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2520                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2521                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2522                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2523                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2524                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2525                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2526                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2527                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2528                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2529                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2530                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2531                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2532                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2533                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2534                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2535                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2536                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2537                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2538                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2539                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2540                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2541                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2542                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2543                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2544                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2545                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2546                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2547                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2548                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2549                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2550                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2551                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2552                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2553                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2554                              <1> ;
  2555                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2556                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2557                              <1> INTA00		equ	020h		; 8259 PORT
  2558                              <1> 
  2559                              <1> kb_int:
  2560                              <1> 
  2561                              <1> ; 13/06/2022
  2562                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2563                              <1> ; 17/10/2015 ('ctrlbrk') 
  2564                              <1> ; 05/12/2014
  2565                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2566                              <1> ;	      instead of pc-at bios - 1985-)
  2567                              <1> ; 26/08/2014
  2568                              <1> ;
  2569                              <1> ; 03/06/86  KEYBOARD BIOS
  2570                              <1> ;
  2571                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2572                              <1> ;										;
  2573                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2574                              <1> ;										;
  2575                              <1> ;--------------------------------------------------------------------------------
  2576                              <1> 
  2577                              <1> KB_INT_1:
  2578 00000C5E FB                  <1> 	sti				; ENABLE INTERRUPTS
  2579                              <1> 	;push	ebp
  2580 00000C5F 50                  <1> 	push	eax
  2581 00000C60 53                  <1> 	push	ebx
  2582 00000C61 51                  <1> 	push	ecx
  2583 00000C62 52                  <1> 	push	edx
  2584 00000C63 56                  <1> 	push	esi
  2585 00000C64 57                  <1> 	push	edi
  2586 00000C65 1E                  <1> 	push	ds
  2587 00000C66 06                  <1> 	push	es
  2588 00000C67 FC                  <1> 	cld				; FORWARD DIRECTION
  2589 00000C68 66B81000            <1> 	mov	ax, KDATA
  2590 00000C6C 8ED8                <1> 	mov	ds, ax
  2591 00000C6E 8EC0                <1> 	mov	es, ax
  2592                              <1> 	;
  2593                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2594 00000C70 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2595 00000C72 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2596 00000C77 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2597 00000C78 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2598                              <1> KB_INT_01:
  2599 00000C7D E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2600 00000C7F A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2601 00000C81 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2602                              <1> 	;
  2603                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2604 00000C83 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2605                              <1> 	;
  2606                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2607                              <1> 	;mov	ah, 04Fh		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2608                              <1> 	;stc				; SET CY=1 (IN CASE OF IRET)
  2609                              <1> 	;int	15h			; CASETTE CALL (AL)=KEY SCAN CODE
  2610                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2611                              <1> 	;jc	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2612                              <1> 	;jmp	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2613                              <1> 	;				; EXIT HANDLES HARDWARE EOI AND ENABLE		
  2614                              <1> 	;
  2615                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2616                              <1> KB_INT_02:				;  (AL)= SCAN CODE
  2617 00000C85 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2618 00000C86 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2619 00000C88 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2620                              <1> 	;
  2621                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2622 00000C8A 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2623 00000C8C 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2624                              <1> 	;
  2625                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2626 00000C8E FA                  <1> 	cli				; DISABLE INTERRUPTS
  2627 00000C8F 800D[855B0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2628 00000C96 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2629                              <1> 	;
  2630                              <1> 	;-----	RESEND THE LAST BYTE
  2631                              <1> KB_INT_4:
  2632 00000C9B FA                  <1> 	cli				; DISABLE INTERRUPTS
  2633 00000C9C 800D[855B0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2634 00000CA3 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2635                              <1> 	;
  2636                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2637                              <1> KB_INT_2:
  2638                              <1> 	;push 	ax			; SAVE DATA IN
  2639                              <1> 	; 24/12/2021
  2640 00000CA8 50                  <1> 	push	eax
  2641 00000CA9 E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2642 00000CAE 8A1D[855B0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2643 00000CB4 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2644 00000CB6 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2645 00000CB9 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2646 00000CBB E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2647                              <1> UP0:
  2648                              <1> 	;pop	ax			; RESTORE DATA IN
  2649                              <1> 	; 24/12/2021
  2650 00000CC0 58                  <1> 	pop	eax
  2651                              <1> ;------------------------------------------------------------------------
  2652                              <1> ;	START OF KEY PROCESSING						;
  2653                              <1> ;------------------------------------------------------------------------
  2654 00000CC1 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2655                              <1> 	;
  2656                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2657 00000CC3 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2658                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2659                              <1> 	; 24/12/2021
  2660 00000CC5 7505                <1> 	jne	short K16
  2661 00000CC7 E9E9040000          <1> 	jmp	K62
  2662                              <1> K16:	
  2663 00000CCC 8A3D[865B0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2664                              <1> 	;
  2665                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2666 00000CD2 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2667 00000CD5 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2668 00000CD7 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2669 00000CD9 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2670 00000CDB 7507                <1> 	jne	short RST_RD_ID
  2671 00000CDD 800D[865B0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2672                              <1> RST_RD_ID:
  2673 00000CE4 8025[865B0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2674 00000CEB EB27                <1>         jmp    short ID_EX		; AND EXIT
  2675                              <1> 	; 24/12/2021
  2676                              <1> 	;jmp	K26
  2677                              <1> 	;
  2678                              <1> TST_ID_2:
  2679 00000CED 8025[865B0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2680 00000CF4 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2681 00000CF6 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2682 00000CF8 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2683 00000CFA 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2684                              <1> 	; 24/12/2021
  2685                              <1> 	;jne	K26
  2686                              <1> 	;
  2687                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2688 00000CFC F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2689 00000CFF 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2690 00000D01 800D[835B0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2691 00000D08 E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2692                              <1> KX_BIT:
  2693 00000D0D 800D[865B0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2694 00000D14 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2695                              <1> 	;
  2696                              <1> NOT_ID:
  2697 00000D19 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2698 00000D1B 750E                <1> 	jne	short TEST_E1
  2699 00000D1D 800D[865B0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2700 00000D24 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2701                              <1> 	; 24/12/2021
  2702 00000D26 E9DA010000          <1> 	jmp	K26A	
  2703                              <1> TEST_E1:	
  2704 00000D2B 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2705 00000D2D 750C                <1> 	jne	short NOT_HC
  2706 00000D2F 800D[865B0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2707 00000D36 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2708                              <1> 	;
  2709                              <1> NOT_HC:
  2710 00000D3B 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2711 00000D3D F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2712 00000D40 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2713                              <1> 	;
  2714 00000D42 BF[6E5A0000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2715 00000D47 AE                  <1> 	scasb
  2716                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2717                              <1> 	; 24/12/2021
  2718 00000D48 7458                <1> 	je	short K16B
  2719 00000D4A AE                  <1> 	scasb
  2720 00000D4B 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2721 00000D4D EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2722                              <1> 	; 24/12/2021
  2723                              <1> 	;jmp	K26
  2724                              <1> 	;
  2725                              <1> NOT_LC_E0:
  2726 00000D4F F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2727 00000D52 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2728 00000D54 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2729 00000D59 BF[6C5A0000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2730 00000D5E F2AE                <1> 	repne	scasb			; CHECK IT
  2731 00000D60 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2732                              <1> 	; 24/12/2021
  2733                              <1> 	;je	K26A			
  2734                              <1> 	;
  2735 00000D62 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2736 00000D64 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2737                              <1> 	; 24/12/2021
  2738                              <1> 	;jne	K26
  2739 00000D66 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2740 00000D69 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2741                              <1> 	; 24/12/2021
  2742                              <1> 	;jnz	K26
  2743                              <1>         ; 20/02/2015 
  2744 00000D6B F605[845B0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2745 00000D72 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2746                              <1> 	; 24/12/2021
  2747                              <1> 	;jnz	K26
  2748 00000D74 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2749                              <1> 	;
  2750                              <1> 	;-----	TEST FOR SYSTEM KEY
  2751                              <1> T_SYS_KEY:
  2752 00000D79 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2753 00000D7B 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2754                              <1> 	;
  2755 00000D7D F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2756 00000D80 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2757                              <1> 	;
  2758 00000D82 F605[845B0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2759 00000D89 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2760                              <1> 	;jnz	K26			
  2761                              <1> 	;
  2762 00000D8B 800D[845B0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2763 00000D92 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2764 00000D94 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2765                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2766 00000D96 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2767 00000D98 E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2768                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2769                              <1> 	;mov	al, 8500h		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2770                              <1> 	;sti				; MAKE SURE INTERRUPTS ENABLED
  2771                              <1> 	;int	15h			; USER INTERRUPT	
  2772 00000D9D E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2773                              <1> 	;
  2774 00000DA2 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2775                              <1> 	;
  2776                              <1> K16C:
  2777 00000DA7 8025[845B0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2778 00000DAE B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2779 00000DB0 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2780                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2781                              <1> 	;mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2782                              <1> 	;call	SHIP_IT			; EXECUTE ENABLE
  2783                              <1> 	;
  2784                              <1> 	;mov	ax, 8501h		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2785                              <1> 	;sti				; MAKE SURE INTERRUPTS ENABLED
  2786                              <1> 	;int	15h			; USER INTERRUPT
  2787                              <1> 	;jmp	K27A			; IGNORE SYSTEM KEY				
  2788                              <1> 	;
  2789 00000DB2 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2790                              <1> 	;
  2791                              <1> 	;-----	TEST FOR SHIFT KEYS
  2792                              <1> K16A:
  2793 00000DB7 8A1D[835B0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2794 00000DBD BF[685A0000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2795 00000DC2 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2796 00000DC7 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2797 00000DC9 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2798                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2799                              <1> 	; 24/12/2021
  2800 00000DCB 7405                <1> 	je	short K17
  2801 00000DCD E914010000          <1> 	jmp	K25
  2802                              <1> 	;
  2803                              <1> 	;------	SHIFT KEY FOUND
  2804                              <1> K17:
  2805 00000DD2 81EF[695A0000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2806 00000DD8 8AA7[705A0000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2807 00000DDE B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2808 00000DE0 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2809                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2810                              <1> 	; 24/12/2021
  2811 00000DE2 7405                <1> 	jz	short K17C
  2812 00000DE4 E999000000          <1> 	jmp	K23
  2813                              <1> 	;
  2814                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2815                              <1> K17C:
  2816 00000DE9 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2817 00000DEC 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2818                              <1> 	;
  2819                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2820 00000DEE 0825[835B0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2821 00000DF4 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2822 00000DF6 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2823                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2824                              <1> 	; 24/12/2021
  2825 00000DF8 E901010000          <1> 	jmp	K26
  2826                              <1> K17D:
  2827 00000DFD F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2828 00000E00 740B                <1> 	jz 	short K17E		; NO, JUMP
  2829 00000E02 0825[865B0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2830 00000E08 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2831                              <1> K17E:
  2832 00000E0D D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2833 00000E0F 0825[845B0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2834 00000E15 E9E4000000          <1> 	jmp	K26
  2835                              <1> 	;
  2836                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2837                              <1> K18:					; SHIFT-TOGGLE
  2838 00000E1A F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2839 00000E1D 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2840                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2841                              <1> 	; 24/12/2021
  2842 00000E1F E9C2000000          <1> 	jmp	K25
  2843                              <1> K18A:
  2844 00000E24 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2845 00000E26 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2846 00000E28 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2847 00000E2B 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2848                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2849                              <1> 	; 24/12/2021
  2850 00000E2D E9B4000000          <1> 	jmp	K25
  2851                              <1> K18B:
  2852 00000E32 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2853 00000E35 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2854                              <1> K19:	
  2855 00000E37 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2856 00000E3A 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2857 00000E3C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2858 00000E3F 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2859                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2860 00000E41 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2861 00000E43 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2862                              <1> K21:					; MIGHT BE NUMERIC
  2863 00000E48 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2864 00000E4B 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2865                              <1> 	;
  2866                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2867 00000E4D 8425[845B0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2868                              <1> 	;jnz	K26
  2869                              <1> 	; 24/12/2021
  2870 00000E53 7405                <1> 	jz	short K22A
  2871 00000E55 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2872                              <1> K22A:
  2873 00000E5A 0825[845B0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2874 00000E60 3025[835B0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2875                              <1> 	;
  2876                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2877 00000E66 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2878 00000E69 7407                <1> 	jz	short K22B		; GO IF NOT
  2879                              <1> 	;
  2880                              <1> 	; 24/12/2021
  2881                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2882 00000E6B 50                  <1> 	push	eax
  2883 00000E6C E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2884                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2885 00000E71 58                  <1> 	pop	eax
  2886                              <1> K22B:
  2887 00000E72 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2888                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2889                              <1> 	; 24/12/2021
  2890 00000E74 7405                <1> 	je	short K22C
  2891 00000E76 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2892                              <1> K22C:
  2893 00000E7B 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2894 00000E7D E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2895                              <1> 	;
  2896                              <1> 	;-----	BREAK SHIFT FOUND
  2897                              <1> K23:					; BREAK-SHIFT-FOUND
  2898 00000E82 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2899 00000E85 F6D4                <1> 	not	ah			; INVERT MASK
  2900 00000E87 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2901 00000E89 2025[835B0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2902 00000E8F 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2903 00000E92 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2904                              <1> 	;
  2905 00000E94 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2906 00000E97 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2907 00000E99 2025[865B0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2908 00000E9F EB08                <1> 	jmp	short K23B		; CONTINUE
  2909                              <1> K23A:
  2910 00000EA1 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2911 00000EA3 2025[845B0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2912                              <1> K23B:
  2913 00000EA9 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2914 00000EAB A0[865B0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2915 00000EB0 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2916 00000EB2 0A05[845B0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2917 00000EB8 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2918 00000EBA 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2919 00000EBC 0805[835B0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2920 00000EC2 88E0                <1> 	mov	al, ah
  2921                              <1> K23D:
  2922 00000EC4 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2923 00000EC6 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2924                              <1> 	;	
  2925                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2926 00000EC8 A0[875B0000]        <1> 	mov	al, [ALT_INPUT]
  2927 00000ECD B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2928 00000ECF 8825[875B0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2929 00000ED5 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2930 00000ED7 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2931 00000ED9 E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2932                              <1> 	;
  2933                              <1> K24:					; BREAK-TOGGLE
  2934 00000EDE 2025[845B0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2935 00000EE4 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2936                              <1> 	;
  2937                              <1> 	;-----	TEST FOR HOLD STATE
  2938                              <1> 					; AL, AH = SCAN CODE
  2939                              <1> K25:					; NO-SHIFT-FOUND
  2940 00000EE6 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2941 00000EE8 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2942 00000EEA F605[845B0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2943 00000EF1 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2944 00000EF3 3C45                <1> 	cmp	al, NUM_KEY
  2945 00000EF5 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2946 00000EF7 8025[845B0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2947                              <1> 	;
  2948                              <1> K26:
  2949 00000EFE 8025[865B0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2950                              <1> K26A:					; INTERRUPT-RETURN
  2951 00000F05 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2952 00000F06 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2953 00000F08 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2954                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2955 00000F0A B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2956 00000F0C E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2957                              <1> K27A:
  2958 00000F11 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2959 00000F12 07                  <1> 	pop	es			; RESTORE REGISTERS
  2960 00000F13 1F                  <1> 	pop	ds
  2961 00000F14 5F                  <1> 	pop	edi
  2962 00000F15 5E                  <1> 	pop	esi
  2963 00000F16 5A                  <1> 	pop	edx
  2964 00000F17 59                  <1> 	pop	ecx
  2965 00000F18 5B                  <1> 	pop	ebx
  2966 00000F19 58                  <1> 	pop	eax
  2967                              <1> 	;pop	ebp
  2968 00000F1A CF                  <1> 	iret				; RETURN
  2969                              <1> 
  2970                              <1> 	;-----	NOT IN	HOLD STATE
  2971                              <1> K28:					; NO-HOLD-STATE
  2972 00000F1B 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2973 00000F1D 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2974                              <1> 	;
  2975 00000F1F F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2976 00000F22 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2977                              <1>         ; 24/12/2021
  2978                              <1> 	;jz	K38
  2979                              <1> 	;
  2980 00000F24 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2981 00000F27 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2982                              <1> 	; 28/02/2015
  2983 00000F29 F605[845B0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2984 00000F30 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2985                              <1> 	; 24/12/2021
  2986                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2987                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2988 00000F32 E9CD000000          <1> K28A:	jmp	K38
  2989                              <1> 	;
  2990                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2991                              <1> K29:					; TEST-RESET
  2992 00000F37 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2993 00000F3A 740B                <1> 	jz	short K31		; NO_RESET
  2994 00000F3C 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2995 00000F3E 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2996                              <1> 	;
  2997                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2998                              <1>  	; 26/08/2014
  2999                              <1> cpu_reset:
  3000                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  3001                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  3002 00000F40 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  3003 00000F42 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  3004                              <1> khere:
  3005 00000F44 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  3006 00000F45 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  3007                              <1> 
  3008                              <1> 	;
  3009                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  3010                              <1> K31:					; NO-RESET
  3011 00000F47 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  3012 00000F49 7507                <1> 	jne	short K311		; NOT THERE
  3013 00000F4B B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  3014 00000F4D E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  3015                              <1> K311:
  3016 00000F52 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  3017 00000F54 7509                <1> 	jne	short K312		; NOT THERE
  3018 00000F56 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  3019 00000F5A E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  3020                              <1> K312:
  3021 00000F5F 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  3022 00000F61 7471                <1>         je	short K37B              ; GO PROCESS
  3023 00000F63 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  3024 00000F65 746D                <1>         je	short K37B              ; GO PROCESS
  3025                              <1> 	;
  3026                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  3027                              <1> K32:					; ALT-KEY-PAD
  3028 00000F67 BF[445A0000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  3029 00000F6C B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  3030 00000F71 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  3031 00000F73 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  3032 00000F75 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  3033                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  3034                              <1> 	; 24/12/2021
  3035 00000F78 751C                <1> 	jnz	short K32B
  3036 00000F7A 81EF[455A0000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  3037 00000F80 A0[875B0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  3038 00000F85 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  3039 00000F87 F6E4                <1> 	mul	ah
  3040 00000F89 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  3041 00000F8C A2[875B0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  3042                              <1> K32A:
  3043 00000F91 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  3044                              <1> K32B:
  3045                              <1> 	; 24/12/2021
  3046 00000F96 EB66                <1> 	jmp	K37C
  3047                              <1> 	;
  3048                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  3049                              <1> K33:					; NO-ALT-KEYPAD
  3050 00000F98 C605[875B0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  3051 00000F9F B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  3052 00000FA4 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  3053 00000FA6 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  3054                              <1> 	;
  3055                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  3056                              <1> K34:					; ALT-TOP-ROW
  3057 00000FA8 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  3058 00000FAA 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  3059 00000FAC 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  3060 00000FAE 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  3061 00000FB0 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  3062 00000FB3 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3063                              <1> 	;
  3064                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  3065                              <1> K35:					; ALT-FUNCTION
  3066 00000FB5 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  3067 00000FB7 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  3068 00000FB9 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  3069 00000FBB 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  3070 00000FBD 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  3071 00000FC0 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3072                              <1> K35A:
  3073 00000FC2 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  3074 00000FC5 7425                <1> 	jz	short K37		; NO, JUMP
  3075 00000FC7 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3076 00000FC9 7510                <1>         jne     short K35B              ; NOT THERE
  3077 00000FCB 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3078 00000FCF E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  3079                              <1> K37B:
  3080 00000FD4 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3081 00000FD6 E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3082                              <1> K35B:
  3083 00000FDB 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3084 00000FDD 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3085 00000FDF 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3086 00000FE1 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3087                              <1>         ; 24/12/2021
  3088                              <1> 	;jne	K26
  3089 00000FE3 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3090 00000FE7 E998010000          <1> 	jmp	K57			; BUFFER FILL
  3091                              <1> K37:
  3092 00000FEC 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3093 00000FEE 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3094 00000FF0 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3095 00000FF2 779D                <1>         ja	short K32A		; IF SO, IGNORE
  3096                              <1> 	; 13/06/2022
  3097                              <1>         ;ja	K26
  3098 00000FF4 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3099                              <1> K37A:
  3100 00000FF7 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3101 00000FF9 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3102                              <1> K37C:
  3103 00000FFE 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3104 00001000 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3105 00001002 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3106                              <1> 	;
  3107                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3108                              <1> K38:					; NOT-ALT-SHIFT
  3109                              <1> 					; BL STILL HAS SHIFT FLAGS
  3110 00001004 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3111 00001007 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3112                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3113                              <1> 	; 24/12/2021
  3114 00001009 E9AB000000          <1> 	jmp	K44
  3115                              <1> 	;
  3116                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3117                              <1> 	;-----	TEST FOR BREAK
  3118                              <1> K38A:
  3119 0000100E 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3120 00001010 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3121 00001012 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3122 00001015 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3123 00001017 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3124 0000101A 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3125                              <1> K38B:
  3126 0000101C 8B1D[905B0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3127 00001022 891D[945B0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3128 00001028 C605[825B0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3129                              <1> 	;
  3130                              <1> 	;-----	ENABLE KEYBOARD
  3131 0000102F B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3132 00001031 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3133                              <1> 	;
  3134                              <1> 	; CTRL+BREAK code here !!!
  3135                              <1> 	;int	1Bh			; BREAK INTERRUPT VECTOR
  3136                              <1> 	; 17/10/2015	
  3137 00001036 E88C190000          <1> 	call	ctrlbrk ; control+break subroutine
  3138                              <1> 	;
  3139                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3140                              <1> 	; 24/12/2021
  3141 0000103B 29C0                <1> 	sub	eax, eax
  3142 0000103D E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3143                              <1> 	;
  3144                              <1> 	;-----	TEST FOR PAUSE
  3145                              <1> K39:					; NO_BREAK
  3146 00001042 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3147 00001045 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3148 00001047 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3149 00001049 7533                <1> 	jne	short K41		; NO-PAUSE
  3150                              <1> K39P:
  3151 0000104B 800D[845B0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3152                              <1> 	;
  3153                              <1> 	;-----	ENABLE KEYBOARD
  3154 00001052 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3155 00001054 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3156                              <1> K39A:
  3157 00001059 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3158 0000105B E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3159                              <1> 	;
  3160                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3161 0000105D 803D[805B0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3162 00001064 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3163 00001066 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3164 0000106A A0[815B0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3165 0000106F EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3166                              <1> 	;
  3167                              <1> K40:					; PAUSE-LOOP
  3168 00001070 F605[845B0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3169 00001077 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3170                              <1> 	;
  3171 00001079 E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3172                              <1>         ;
  3173                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3174                              <1> K41:					; NO-PAUSE
  3175 0000107E 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3176 00001080 7513                <1> 	jne	short K42		; NOT-KEY-55
  3177 00001082 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3178 00001085 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3179 00001087 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3180 0000108A 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3181                              <1> K41A:	
  3182 0000108C 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3183 00001090 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3184                              <1> 	;
  3185                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3186                              <1> K42:					; NOT-KEY-55
  3187 00001095 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3188 00001097 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3189 00001099 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3190 0000109B 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3191 0000109D F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3192 000010A0 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3193 000010A2 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3194 000010A6 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3195                              <1> K42A:
  3196                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3197 000010AB 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3198                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3199                              <1> 	;;jb	K56 ; 20/02/2015
  3200                              <1> 	;;jmp	K64 ; 20/02/2015
  3201                              <1> K42B:
  3202 000010AD BB[785A0000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3203                              <1> 	;;jmp	K64
  3204                              <1> 	;jb	K56 ;; 20/02/2015	
  3205                              <1> 	; 24/12/2021
  3206 000010B2 7267                <1> 	jb	short K45F
  3207 000010B4 E9B9000000          <1> 	jmp	K64	
  3208                              <1>         ;
  3209                              <1> 	;-----	NOT IN CONTROL SHIFT
  3210                              <1> K44:					; NOT-CTL-SHIFT
  3211 000010B9 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3212 000010BB 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3213 000010BD F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3214 000010C0 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3215 000010C2 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3216 000010C5 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3217 000010C7 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3218                              <1> K44A:
  3219 000010C9 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3220 000010CC 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3221                              <1> 	;
  3222                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3223                              <1> K44B:
  3224 000010CE B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3225 000010D0 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3226 000010D5 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3227 000010D7 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3228                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3229                              <1> 	;push	bp			; SAVE POINTER
  3230                              <1> 	;int	05h			; ISSUE PRINT SCREEN INTERRUPT
  3231                              <1> 	;pop	bp			; RESTORE POINTER
  3232 000010D9 8025[865B0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3233 000010E0 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3234                              <1> 	;
  3235                              <1> 	;-----	HANDLE IN-CORE KEYS
  3236                              <1> K45:					; NOT-PRINT-SCREEN
  3237 000010E5 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3238 000010E7 7734                <1> 	ja	short K46		; JUMP IF NOT
  3239 000010E9 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3240 000010EB 7505                <1> 	jne	short K45A		; NO, JUMP
  3241 000010ED F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3242 000010F0 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3243                              <1> K45A:
  3244 000010F2 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3245 000010F7 BF[4E5A0000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3246 000010FC F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3247                              <1> 		; 20/02/2015
  3248 000010FE 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3249                              <1> 	;
  3250 00001100 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3251 00001103 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3252                              <1> K45B:
  3253 00001105 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3254 00001108 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3255                              <1> 					; NO, LOWERCASE
  3256                              <1> K45C:
  3257 0000110A BB[D05A0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3258 0000110F EB51                <1> 	jmp	short K56	
  3259                              <1> K45D:					; ALMOST-CAPS-STATE
  3260 00001111 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3261 00001114 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3262                              <1> K45E:
  3263 00001116 BB[285B0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3264 0000111B EB45                <1> K45F:	jmp	short K56
  3265                              <1> 	;
  3266                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3267                              <1> K46:					; NOT IN-CORE AREA
  3268 0000111D 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3269                              <1> 	;ja	short K47		; JUMP IF NOT
  3270                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3271 0000111F 7635                <1> 	jna	short K53		
  3272                              <1> 	;
  3273                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3274                              <1> K47:					; NOT F1 - F10
  3275 00001121 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3276 00001123 772D                <1> 	ja	short K52		; JUMP IF NOT
  3277                              <1> 	;
  3278                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3279                              <1> K48:
  3280 00001125 3C4A                <1> 	cmp	al, 74			; SPECIAL CASE FOR MINUS
  3281 00001127 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3282 00001129 3C4E                <1> 	cmp	al, 78			; SPECIAL CASE FOR PLUS
  3283 0000112B 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3284 0000112D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3285 00001130 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3286                              <1> 	;		
  3287 00001132 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3288 00001135 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3289 00001137 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3290                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3291 0000113A 75DA                <1> 	jnz	short K45E
  3292                              <1> 	;
  3293                              <1> 	;-----	BASE CASE FOR KEYPAD
  3294                              <1> K49:					
  3295 0000113C 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3296 0000113E 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3297 00001140 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3298 00001142 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3299                              <1> K49A:
  3300 00001144 BB[D05A0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3301 00001149 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3302                              <1> 	;
  3303                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3304                              <1> K50:					; ALMOST-NUM-STATE
  3305 0000114B F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3306 0000114E 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3307 00001150 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3308                              <1> 	;
  3309                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3310                              <1> K52:					; NOT A NUMPAD KEY
  3311 00001152 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3312                              <1> 	;jne	short K53		; JUMP IF NOT
  3313                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3314 00001154 74AF                <1> 	je	short K45B		
  3315                              <1> 	;
  3316                              <1> 	;-----	MUST BE F11 OR F12 
  3317                              <1> K53:					; F1 - F10 COME HERE, TOO
  3318 00001156 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3319 00001159 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3320                              <1> 		; 20/02/2015 
  3321 0000115B BB[285B0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3322 00001160 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3323                              <1> 	;
  3324                              <1> 	;-----	TRANSLATE THE CHARACTER
  3325                              <1> K56:					; TRANSLATE-CHAR
  3326 00001162 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3327 00001164 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3328 00001165 F605[865B0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3329 0000116C 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3330 0000116E B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3331 00001170 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3332                              <1> 	;
  3333                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3334                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3335 00001172 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3336 00001174 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3337 00001175 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3338 00001177 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3339 00001179 F605[865B0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3340 00001180 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3341 00001182 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3342                              <1> 	;
  3343                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3344                              <1> K57:					; BUFFER_FILL
  3345 00001184 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3346 00001186 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3347                              <1> 	; 24/12/2021
  3348                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3349 00001188 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3350                              <1> 	; 24/12/2021
  3351 0000118B 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3352                              <1> 	;je	K26			; INTERRUPT_RETURN
  3353                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3354 0000118D E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3355                              <1> K61:					; NOT-CAPS-STATE
  3356 00001192 8B1D[945B0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3357 00001198 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3358 0000119A E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3359 0000119F 3B1D[905B0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3360 000011A5 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3361 000011A7 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3362 000011AA 891D[945B0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3363 000011B0 E949FDFFFF          <1> 	jmp	K26
  3364                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3365                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3366                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3367                              <1> 	;mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3368                              <1> 	;call	SHIP_IT			; EXECUTE ENABLE
  3369                              <1> 	;mov	ax, 9102h		; MOVE IN POST CODE & TYPE
  3370                              <1> 	;int	15h			; PERFORM OTHER FUNCTION
  3371                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3372                              <1> 	;jmp	K27A			; INTERRUPT_RETURN
  3373                              <1> 	;;jmp   K27                    
  3374                              <1> 	;
  3375                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3376                              <1> K62:
  3377 000011B5 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3378 000011B7 E620                <1> 	out	INTA00, al
  3379 000011B9 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3380 000011BD B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3381 000011BF E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3382 000011C4 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3383                              <1> 
  3384                              <1> SHIP_IT:
  3385                              <1> 	;---------------------------------------------------------------------------------
  3386                              <1> 	; SHIP_IT
  3387                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3388                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3389                              <1> 	;---------------------------------------------------------------------------------
  3390                              <1> 	;
  3391                              <1> 	;push	ax			; SAVE DATA TO SEND
  3392                              <1> 	; 24/12/2021
  3393 000011C9 50                  <1> 	push	eax
  3394                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3395 000011CA FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3396                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3397 000011CB B900000100          <1> 	mov	ecx, 10000h			
  3398                              <1> S10:
  3399 000011D0 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3400 000011D2 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3401 000011D4 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3402                              <1> 
  3403                              <1> 	;pop	ax			; GET DATA TO SEND
  3404                              <1> 	; 24/12/2021
  3405 000011D6 58                  <1> 	pop	eax
  3406 000011D7 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3407 000011D9 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3408 000011DA C3                  <1> 	retn				; RETURN TO CALLER
  3409                              <1> 
  3410                              <1> SND_DATA:
  3411                              <1> 	; ---------------------------------------------------------------------------------
  3412                              <1> 	; SND_DATA
  3413                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3414                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3415                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3416                              <1> 	; ---------------------------------------------------------------------------------
  3417                              <1> 	;
  3418                              <1> 	;push	ax			; SAVE REGISTERS
  3419                              <1> 	;push	bx
  3420                              <1> 	; 24/12/2021
  3421 000011DB 50                  <1> 	push	eax
  3422 000011DC 53                  <1> 	push	ebx
  3423 000011DD 51                  <1> 	push	ecx
  3424 000011DE 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3425 000011E0 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3426                              <1> SD0:
  3427 000011E2 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3428 000011E3 8025[855B0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3429                              <1> 	;
  3430                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3431 000011EA B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3432                              <1> SD5:
  3433 000011EF E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3434 000011F1 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3435 000011F3 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3436                              <1> 	;
  3437 000011F5 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3438 000011F7 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3439 000011F9 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3440                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3441 000011FA B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3442                              <1> SD1:
  3443 000011FF F605[855B0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3444 00001206 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3445 00001208 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3446                              <1> SD2:
  3447 0000120A FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3448 0000120C 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3449 0000120E 800D[855B0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3450 00001215 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3451                              <1> SD3:
  3452 00001217 F605[855B0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3453 0000121E 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3454                              <1> SD4:	
  3455 00001220 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3456                              <1> 	;pop	bx
  3457                              <1> 	;pop	ax
  3458                              <1> 	; 24/12/2021
  3459 00001221 5B                  <1> 	pop	ebx
  3460 00001222 58                  <1> 	pop	eax
  3461 00001223 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3462                              <1> 
  3463                              <1> SND_LED:
  3464                              <1> 	; ---------------------------------------------------------------------------------
  3465                              <1> 	; SND_LED
  3466                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3467                              <1> 	;
  3468                              <1> 	;----------------------------------------------------------------------------------
  3469                              <1> 	;
  3470 00001224 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3471 00001225 F605[855B0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3472 0000122C 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3473                              <1> 	;
  3474 0000122E 800D[855B0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3475 00001235 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3476 00001237 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3477 00001239 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3478                              <1> SND_LED1:
  3479 0000123B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3480 0000123C F605[855B0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3481 00001243 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3482                              <1> 	;
  3483 00001245 800D[855B0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3484                              <1> SL0:
  3485 0000124C B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3486 0000124E E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3487 00001253 FA                  <1> 	cli
  3488 00001254 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3489 00001259 8025[855B0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3490 00001260 0805[855B0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3491 00001266 F605[855B0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3492 0000126D 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3493                              <1> 	;
  3494 0000126F E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3495 00001274 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3496 00001275 F605[855B0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3497 0000127C 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3498                              <1> SL2:
  3499 0000127E B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3500 00001280 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3501 00001285 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3502                              <1> SL3:
  3503 00001286 8025[855B0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3504                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3505 0000128D FB                  <1> 	sti				; ENABLE INTERRUPTS
  3506 0000128E C3                  <1> 	retn				; RETURN TO CALLER
  3507                              <1> 
  3508                              <1> MAKE_LED:
  3509                              <1> 	;---------------------------------------------------------------------------------
  3510                              <1> 	; MAKE_LED
  3511                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3512                              <1> 	;	THE MODE INDICATORS.
  3513                              <1> 	;---------------------------------------------------------------------------------
  3514                              <1> 	;
  3515                              <1> 	;push 	cx			; SAVE CX
  3516 0000128F A0[835B0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3517 00001294 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3518                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3519                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3520 00001296 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3521 00001299 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3522                              <1> 	;pop	cx
  3523 0000129B C3                  <1> 	retn				; RETURN TO CALLER
  3524                              <1> 
  3525                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3526                              <1> 
  3527                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1892                                  
  1893                                  %include 'video.inc' ; 07/03/2015
  1894                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - VIDEO.INC
  1895                              <1> ; Last Modification: 14/06/2022
  1896                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1897                              <1> ;
  1898                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1899                              <1> 
  1900                              <1> ; 14/06/2022
  1901                              <1> ; 26/02/2022
  1902                              <1> ; 07/02/2022
  1903                              <1> ; 02/02/2022 (simplified scroll up)
  1904                              <1> ; 16/01/2016
  1905                              <1> ; 30/06/2015
  1906                              <1> ; 27/06/2015
  1907                              <1> ; 11/03/2015
  1908                              <1> ; 02/09/2014
  1909                              <1> ; 30/08/2014
  1910                              <1> ; VIDEO FUNCTIONS
  1911                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1912                              <1> 
  1913                              <1> write_tty:
  1914                              <1> 	; 02/02/2022
  1915                              <1> 	; 13/08/2015
  1916                              <1> 	; 02/09/2014
  1917                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1918                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1919                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1920                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1921                              <1> 	;
  1922                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1923                              <1> 	;	   AL = Character to be written
  1924                              <1> 	;	   EBX = Video Page (0 to 7)
  1925                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1926                              <1> 
  1927                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1928                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1929                              <1> 
  1930                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1931                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1932                              <1> ;
  1933                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1934                              <1> ;
  1935                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1936                              <1> ;										:
  1937                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1938                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1939                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1940                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1941                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1942                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1943                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1944                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1945                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1946                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1947                              <1> ;   THE 0 COLOR IS USED.							:
  1948                              <1> ;   ENTRY --									:
  1949                              <1> ;     (AH) = CURRENT CRT MODE							:
  1950                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1951                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1952                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1953                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1954                              <1> ;   EXIT -- 									:
  1955                              <1> ;     ALL REGISTERS SAVED							:
  1956                              <1> ;--------------------------------------------------------------------------------
  1957                              <1> 
  1958 0000129C FA                  <1> 	cli
  1959                              <1> 	;
  1960                              <1> 	; READ CURSOR (04/12/2013)
  1961                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1962 0000129D 08FF                <1> 	or	bh, bh
  1963                              <1> 	;jnz	beeper
  1964                              <1> 	; 02/02/2022
  1965 0000129F 7405                <1> 	jz	short u14
  1966 000012A1 E992000000          <1> 	jmp	beeper
  1967                              <1> u14:
  1968                              <1> 	; 02/02/2022
  1969                              <1> 	;; 01/09/2014
  1970                              <1> 	;cmp	byte [CRT_MODE], 3
  1971                              <1> 	;je	short m3
  1972                              <1> 	;;
  1973                              <1> 	;call	set_mode
  1974                              <1> m3:
  1975 000012A6 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1976                              <1> 	;shl	si, 1
  1977                              <1> 	; 02/02/2022
  1978 000012A8 D1E6                <1> 	shl	esi, 1
  1979 000012AA 81C6[46610000]      <1> 	add	esi, cursor_posn
  1980 000012B0 668B16              <1> 	mov	dx, [esi]
  1981                              <1> 	;
  1982                              <1> 	; dx now has the current cursor position
  1983                              <1> 	;
  1984 000012B3 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1985 000012B5 7647                <1> 	jbe	short u8
  1986                              <1> 	;
  1987                              <1> 	; write the char to the screen
  1988                              <1> u0:	
  1989                              <1> 	; ah = attribute/color
  1990                              <1> 	; al = character
  1991                              <1> 	; bl = video page number (0 to 7)
  1992                              <1> 	; bh = 0
  1993                              <1> 	;
  1994 000012B7 E8D2010000          <1> 	call	write_c_current
  1995                              <1> 	;
  1996                              <1> 	; position the cursor for next char
  1997 000012BC FEC2                <1> 	inc	dl		; next column
  1998                              <1> 	;cmp	dl, [CRT_COLS]
  1999 000012BE 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  2000                              <1>         ;jne	set_cpos
  2001                              <1> 	; 02/02/2022
  2002 000012C1 7405                <1> 	je	short u13
  2003 000012C3 E9DE000000          <1> 	jmp	set_cpos
  2004                              <1> u13:
  2005 000012C8 B200                <1> 	mov	dl, 0		; column = 0
  2006                              <1> u10:				; (line feed found)
  2007 000012CA 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  2008 000012CD 7228                <1> 	jb 	short u6
  2009                              <1> 	;
  2010                              <1> 	; scroll required
  2011                              <1> u1:	
  2012                              <1> 	; SET CURSOR POSITION (04/12/2013)
  2013 000012CF E8D2000000          <1> 	call	set_cpos
  2014                              <1> 	;
  2015                              <1> 	; determine value to fill with during scroll
  2016                              <1> u2:
  2017                              <1> 	; READ_AC_CURRENT		:
  2018                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  2019                              <1> 	;    AT THE CURRENT CURSOR POSITION
  2020                              <1> 	;
  2021                              <1> 	; INPUT				
  2022                              <1> 	;	(AH) = CURRENT CRT MODE
  2023                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2024                              <1> 	;	(DS) = DATA SEGMENT
  2025                              <1> 	;	(ES) = REGEN SEGMENT
  2026                              <1> 	; OUTPUT			
  2027                              <1> 	;	(AL) = CHARACTER READ
  2028                              <1> 	;	(AH) = ATTRIBUTE READ
  2029                              <1> 	;
  2030                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2031                              <1> 	;
  2032                              <1> 	; bl = video page number
  2033                              <1> 	;
  2034 000012D4 E829010000          <1> 	call	find_position	; get regen location and port address
  2035                              <1> 	; dx = status port
  2036                              <1> 	; esi = cursor location/address
  2037                              <1> p11:
  2038 000012D9 FB                  <1> 	sti			; enable interrupts
  2039 000012DA 90                  <1> 	nop			; allow for small interupts window
  2040 000012DB FA                  <1> 	cli			; blocks interrupts for single loop
  2041 000012DC EC                  <1> 	in	al, dx		; get status from adapter
  2042 000012DD A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2043 000012DF 75F8                <1> 	jnz	short p11	; wait until it is
  2044                              <1> p12:				; now wait for either retrace high
  2045 000012E1 EC                  <1> 	in	al, dx		; get status
  2046 000012E2 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2047 000012E4 74FB                <1> 	jz	short p12	; wait until either is active	
  2048                              <1> p13:
  2049 000012E6 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2050 000012EC 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2051                              <1> 	;
  2052                              <1> 	; al = character, ah = attribute
  2053                              <1> 	;
  2054 000012EF FB                  <1> 	sti
  2055                              <1> 	; bl = video page number 	
  2056                              <1> u3:
  2057                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2058                              <1> 	;;sub	cx, cx		; upper left corner
  2059                              <1> 	;;mov	dh, 25-1 	; lower right row
  2060                              <1> 	;;;mov	dl, [CRT_COLS]
  2061                              <1> 	;mov	dl, 80		; lower right column	
  2062                              <1> 	;;dec	dl
  2063                              <1> 	;;mov	dl, 79
  2064                              <1> 
  2065                              <1> 	;;call	scroll_up	; 04/12/2013
  2066                              <1> 	;;; 11/03/2015
  2067                              <1> 	; 02/09/2014
  2068                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2069                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2070                              <1> 	; 11/03/2015
  2071                              <1> 	;sub	cx, cx
  2072                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2073                              <1> 	;
  2074                              <1> 	; 02/02/2022 (simplied scroll up)
  2075                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2076                              <1> 	;
  2077 000012F0 B001                <1> 	mov	al, 1		; scroll 1 line up
  2078                              <1> 		; ah = attribute
  2079 000012F2 E935010000          <1> 	jmp	scroll_up
  2080                              <1> ;u4:
  2081                              <1> 	;;int	10h		; video-call return
  2082                              <1> 				; scroll up the screen
  2083                              <1> 				; tty return
  2084                              <1> ;u5:
  2085                              <1> 	;retn			; return to the caller
  2086                              <1> 
  2087                              <1> u6:				; set-cursor-inc
  2088 000012F7 FEC6                <1> 	inc	dh		; next row
  2089                              <1> 				; set cursor
  2090                              <1> ;u7:					
  2091                              <1> 	;;mov	ah, 02h
  2092                              <1> 	;;jmp	short u4 	; establish the new cursor
  2093                              <1> 	;call	set_cpos
  2094                              <1> 	;jmp 	short u5
  2095 000012F9 E9A8000000          <1> 	jmp     set_cpos
  2096                              <1> 
  2097                              <1> 	; check for control characters
  2098                              <1> u8:
  2099 000012FE 7434                <1> 	je	short u9
  2100 00001300 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2101 00001302 74C6                <1> 	je	short u10
  2102 00001304 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2103 00001306 7430                <1> 	je	short u11
  2104 00001308 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2105                              <1> 	;jne	short u0
  2106 0000130A 7420                <1> 	je	short bs	; 12/12/2013
  2107                              <1> 	; 12/12/2013 (tab stop)
  2108 0000130C 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2109 0000130E 75A7                <1> 	jne	short u0
  2110 00001310 88D0                <1> 	mov	al, dl
  2111 00001312 6698                <1> 	cbw
  2112 00001314 B108                <1> 	mov	cl, 8
  2113 00001316 F6F1                <1> 	div	cl
  2114 00001318 28E1                <1> 	sub	cl, ah
  2115                              <1> ts:
  2116                              <1> 	; 02/09/2014
  2117                              <1> 	; 01/09/2014
  2118 0000131A B020                <1> 	mov	al, 20h
  2119                              <1> tsloop:
  2120                              <1> 	;push	cx
  2121                              <1> 	;push	ax
  2122                              <1> 	; 02/02/2022
  2123 0000131C 51                  <1> 	push	ecx
  2124 0000131D 50                  <1> 	push	eax
  2125 0000131E 30FF                <1> 	xor 	bh, bh
  2126                              <1> 	;mov	bl, [active_page]
  2127 00001320 E881FFFFFF          <1> 	call	m3
  2128                              <1> 	; 02/02/2022
  2129 00001325 58                  <1> 	pop	eax
  2130 00001326 59                  <1>  	pop	ecx
  2131                              <1> 	;pop	ax  ; ah = attribute/color
  2132                              <1> 	;pop	cx
  2133 00001327 FEC9                <1> 	dec	cl
  2134 00001329 75F1                <1> 	jnz	short tsloop
  2135 0000132B C3                  <1> 	retn
  2136                              <1> bs:	
  2137                              <1> 	; back space found
  2138 0000132C 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2139                              <1> 	;je	short u7 	; set_cursor
  2140 0000132E 7476                <1> 	jz	short set_cpos
  2141                              <1> 	;dec	dx     		; no -- just move it back
  2142                              <1> 	; 02/02/2022
  2143 00001330 FECA                <1> 	dec	dl
  2144                              <1> 	;jmp	short u7
  2145 00001332 EB72                <1> 	jmp	short set_cpos
  2146                              <1> 
  2147                              <1> 	; carriage return found
  2148                              <1> u9:
  2149 00001334 B200                <1> 	mov	dl, 0 		; move to first column
  2150                              <1> 	;jmp	short u7
  2151 00001336 EB6E                <1> 	jmp	short set_cpos
  2152                              <1> 
  2153                              <1> 	; line feed found
  2154                              <1> ;u10:
  2155                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2156                              <1> ;	jne	short u6 	; no, just set the cursor
  2157                              <1> ;       jmp     u1              ; yes, scroll the screen
  2158                              <1> 
  2159                              <1> beeper: 
  2160                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2161                              <1> 	; 18/01/2014
  2162                              <1> 	; 03/12/2013
  2163                              <1> 	; bell found
  2164                              <1> u11:
  2165 00001338 FB                  <1> 	sti
  2166 00001339 3A1D[56610000]      <1> 	cmp	bl, [active_page]
  2167 0000133F 7551                <1> 	jne	short u12	; Do not sound the beep 
  2168                              <1> 				; if it is not written on the active page
  2169 00001341 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2170 00001345 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2171                              <1> 	;call	beep		; sound the pod bell
  2172                              <1> 	;jmp	short u5 	; tty_return
  2173                              <1> 	;retn
  2174                              <1> 	
  2175                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2176                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2177                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2178                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2179                              <1> 
  2180                              <1> beep:
  2181                              <1> 	; 07/02/2015
  2182                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2183                              <1> 	; 18/01/2014
  2184                              <1> 	; 03/12/2013
  2185                              <1> 	;
  2186                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2187                              <1> 	;
  2188                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2189                              <1> 	;
  2190                              <1> 	; ENTRY:
  2191                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2192                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2193                              <1> 	; EXIT:			:
  2194                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2195                              <1> 
  2196 00001347 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2197 00001348 FA                  <1> 	cli			; block interrupts during update
  2198 00001349 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2199 0000134B E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2200 0000134D EB00                <1> 	jmp	$+2		; I/O delay
  2201 0000134F 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2202 00001351 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2203 00001353 EB00                <1> 	jmp	$+2		; I/O delay
  2204 00001355 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2205 00001357 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2206 00001359 E461                <1> 	in	al, PORT_B	; get current setting of port
  2207 0000135B 88C4                <1> 	mov	ah, al		; save that setting
  2208 0000135D 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2209 0000135F E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2210                              <1> 	;popf	; 18/01/2014
  2211 00001361 FB                  <1> 	sti
  2212                              <1> g7:				; 1/64 second per count (bl)
  2213 00001362 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2214 00001367 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2215 0000136C FECB                <1> 	dec	bl		; (bl) length count expired?
  2216 0000136E 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2217                              <1> 	;
  2218                              <1> 	;pushf			; save interrupt status
  2219 00001370 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2220 00001371 E461                <1> 	in	al, PORT_B	; get current port value
  2221                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2222 00001373 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2223 00001375 20C4                <1>         and	ah, al		; someone turned them off during beep
  2224 00001377 88E0                <1> 	mov	al, ah		; recover value of port
  2225                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2226 00001379 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2227 0000137B E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2228                              <1> 	;popf			; restore interrupt flag state
  2229 0000137D FB                  <1> 	sti
  2230 0000137E B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2231 00001383 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2232                              <1> 	;pushf			; save interrupt status
  2233 00001388 FA                  <1> 	cli			; block interrupts during update
  2234 00001389 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2235 0000138B 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2236 0000138D 08E0                <1> 	or	al, ah		; recover value of port_b
  2237 0000138F E661                <1> 	out	PORT_B, al	; restore speaker status
  2238 00001391 9D                  <1> 	popf			; restore interrupt flag state
  2239                              <1> u12:	
  2240 00001392 C3                  <1> 	retn
  2241                              <1> 
  2242                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2243                              <1> 
  2244                              <1> WAITF:
  2245                              <1> waitf:
  2246                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2247                              <1> 	; 03/12/2013
  2248                              <1> 	;
  2249                              <1> ;	push	ax		; save work register (ah)	
  2250                              <1> ;waitf1:
  2251                              <1> 				; use timer 1 output bits
  2252                              <1> ;	in	al, PORT_B	; read current counter output status
  2253                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2254                              <1> ;	cmp	al, ah		; did it just change
  2255                              <1> ;	je	short waitf1	; wait for a change in output line
  2256                              <1> ;	;
  2257                              <1> ;	mov	ah, al		; save new lflag state
  2258                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2259                              <1> ;	;
  2260                              <1> ;	pop	ax		; restore (ah)
  2261                              <1> ;	retn			; return (cx)=0
  2262                              <1> 
  2263                              <1> ; 02/02/2022
  2264                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2265                              <1> ; 17/12/2014 (dsectrm2.s)
  2266                              <1> ; WAITF
  2267                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2268                              <1> ;
  2269                              <1> ;---WAITF-----------------------------------------------------------------------
  2270                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2271                              <1> ; ENTRY:
  2272                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2273                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2274                              <1> ; EXIT:
  2275                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2276                              <1> ;	(CX) = 0	
  2277                              <1> ;-------------------------------------------------------------------------------
  2278                              <1> 
  2279                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2280                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2281                              <1> 
  2282                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2283 00001393 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2284                              <1> 	;push	ax
  2285                              <1> 	; 16/12/2014
  2286                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2287 00001394 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2288                              <1> ;17/12/2014	
  2289                              <1> ;WAITF1:
  2290                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2291                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2292                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2293                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2294                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2295                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2296                              <1> 	;
  2297                              <1> 	; 17/12/2014
  2298                              <1> 	;
  2299                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2300                              <1> 	;
  2301                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2302                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2303                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2304                              <1> WR_STATE_0:
  2305 00001396 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2306 00001398 A810                <1> 	TEST	AL,010H
  2307 0000139A 74FA                <1> 	JZ	SHORT WR_STATE_0
  2308                              <1> WR_STATE_1:
  2309 0000139C E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2310 0000139E A810                <1> 	TEST	AL,010H
  2311 000013A0 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2312 000013A2 E2F2                <1>         LOOP    WR_STATE_0
  2313                              <1> 	;
  2314                              <1> 	;pop	ax
  2315 000013A4 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2316 000013A5 C3                  <1> 	RETn				; (CX) = 0
  2317                              <1> 
  2318                              <1> set_cpos:
  2319                              <1> 	; 14/06/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.4)
  2320                              <1> 	; 26/02/2022
  2321                              <1> 	; 02/02/2022
  2322                              <1> 	; 27/06/2015
  2323                              <1> 	; 01/09/2014
  2324                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2325                              <1> 	;
  2326                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2327                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2328                              <1> 	;
  2329                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2330                              <1> 	;
  2331                              <1> 	; SET_CPOS
  2332                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2333                              <1> 	;	NEW X-Y VALUES PASSED
  2334                              <1> 	; INPUT
  2335                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2336                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2337                              <1> 	; OUTPUT
  2338                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2339                              <1> 	;
  2340 000013A6 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2341 000013A9 D0E0                <1>         shl     al, 1   ; word offset
  2342 000013AB BE[46610000]        <1> 	mov	esi, cursor_posn
  2343 000013B0 01C6                <1>         add     esi, eax
  2344 000013B2 668916              <1> 	mov	[esi], dx ; save the pointer
  2345 000013B5 381D[56610000]      <1> 	cmp	[active_page], bl
  2346 000013BB 7531                <1> 	jne	short m17
  2347                              <1> 
  2348                              <1> 	; 14/06/2022
  2349                              <1> 	;cli ; 26/02/2022
  2350                              <1> 
  2351                              <1> 	;call	m18	;h CURSOR SET
  2352                              <1> ;m17:			; SET_CPOS_RETURN
  2353                              <1> 	; 01/09/2014
  2354                              <1> 	;retn
  2355                              <1> 		; DX = row/column
  2356                              <1> m18:
  2357 000013BD E832000000          <1> 	call	position ; determine location in regen buffer	
  2358                              <1> 	;mov	cx, [CRT_START]
  2359                              <1> 	; 26/02/2022
  2360 000013C2 0FB70D[44610000]    <1> 	movzx	ecx, word [CRT_START]
  2361 000013C9 01C1                <1> 	add	ecx, eax
  2362                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2363                              <1> 			; to the start address (offset) for this page
  2364                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2365                              <1> 	; 26/02/2022
  2366 000013CB D1E9                <1> 	shr	ecx, 1
  2367 000013CD B40E                <1> 	mov	ah, 14	; register number for cursor
  2368                              <1> 	
  2369                              <1> 	; 14/06/2022
  2370                              <1> 	;call	m16	; output value to the 6845
  2371                              <1> 	;sti	; 26/02/2022
  2372                              <1> 	;retn
  2373                              <1> 
  2374                              <1> 	; 14/06/2022
  2375                              <1> 	; 26/02/2022
  2376                              <1> 	; 02/02/2022
  2377                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2378                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2379                              <1> m16:
  2380                              <1> 	; 14/06/2022
  2381 000013CF FA                  <1> 	cli	; 26/02/2022
  2382                              <1> 	;mov	dx, [addr_6845] ; address register
  2383 000013D0 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2384 000013D4 88E0                <1> 	mov	al, ah	; get value
  2385 000013D6 EE                  <1> 	out	dx, al	; register set
  2386                              <1> 	;inc	dx	; data register
  2387                              <1> 	; 02/02/2022
  2388 000013D7 FEC2                <1> 	inc	dl
  2389 000013D9 EB00                <1> 	jmp	$+2	; i/o delay
  2390 000013DB 88E8                <1> 	mov	al, ch	; data
  2391 000013DD EE                  <1> 	out	dx, al	
  2392                              <1> 	;dec	dx
  2393                              <1> 	; 02/02/2022	
  2394 000013DE FECA                <1> 	dec	dl
  2395 000013E0 88E0                <1> 	mov	al, ah
  2396 000013E2 FEC0                <1> 	inc	al	; point to other data register
  2397 000013E4 EE                  <1> 	out	dx, al	; set for second register
  2398                              <1> 	;inc	dx
  2399                              <1> 	; 02/02/2022
  2400 000013E5 FEC2                <1> 	inc	dl
  2401 000013E7 EB00                <1> 	jmp	$+2	; i/o delay
  2402 000013E9 88C8                <1> 	mov	al, cl	; second data value
  2403 000013EB EE                  <1> 	out	dx, al
  2404                              <1> 	; 14/06/2022
  2405 000013EC FB                  <1> 	sti	; 26/02/2022
  2406                              <1> ;m17:
  2407 000013ED C3                  <1> 	retn
  2408                              <1> m17:
  2409                              <1> 	; 14/06/2022
  2410                              <1> 	; ('write_tty' must not return to 'putc'/'wtty' with cf)
  2411 000013EE F8                  <1> 	clc
  2412 000013EF C3                  <1> 	retn
  2413                              <1> 
  2414                              <1> set_ctype:
  2415                              <1> 	; 07/02/2022
  2416                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2417                              <1> 	;
  2418                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2419                              <1> 
  2420                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2421                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2422                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2423                              <1> ;          OR NO CURSOR AT ALL
  2424                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2425                              <1> 
  2426                              <1> ;------------------------------------------------
  2427                              <1> ; SET_CTYPE
  2428                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2429                              <1> ; INPUT
  2430                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2431                              <1> ; OUTPUT	
  2432                              <1> ;	NONE
  2433                              <1> ;------------------------------------------------
  2434                              <1> 
  2435 000013F0 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2436                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2437                              <1> 	;call	m16	; output cx register
  2438                              <1> 	;retn
  2439                              <1> 	; 07/02/2022
  2440 000013F2 EBDB                <1> 	jmp	short m16
  2441                              <1> 
  2442                              <1> position:
  2443                              <1> 	; 26/02/2022
  2444                              <1> 	; 02/02/2022
  2445                              <1> 	; 27/06/2015
  2446                              <1> 	; 02/09/2014
  2447                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2448                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2449                              <1> 	;
  2450                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2451                              <1> 	;
  2452                              <1> 	; POSITION
  2453                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2454                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2455                              <1> 	; INPUT
  2456                              <1> 	;	AX = ROW, COLUMN POSITION
  2457                              <1> 	; OUTPUT
  2458                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2459                              <1> 
  2460                              <1> 		; DX = ROW, COLUMN POSITION
  2461                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2462 000013F4 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2463 000013F6 B050                <1> 	mov	al, 80	; determine bytes to row	
  2464 000013F8 F6E6                <1> 	mul	dh	; row value
  2465                              <1> 	;xor	dh, dh	; 0
  2466                              <1> 	;add	ax, dx	; add column value to the result
  2467                              <1> 	; 26/02/2022
  2468 000013FA 00D0                <1> 	add	al, dl
  2469 000013FC 80D400              <1> 	adc	ah, 0	
  2470                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2471                              <1> 	; 02/02/2022
  2472 000013FF D1E0                <1> 	shl	eax, 1
  2473                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2474 00001401 C3                  <1> 	retn
  2475                              <1> 
  2476                              <1> find_position:
  2477                              <1> 	; 02/02/2022
  2478                              <1> 	; 27/06/2015
  2479                              <1> 	; 07/09/2014
  2480                              <1> 	; 02/09/2014
  2481                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2482                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2483 00001402 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2484 00001405 89CE                <1> 	mov	esi, ecx
  2485                              <1> 	;shl	si, 1
  2486                              <1> 	; 02/02/2022
  2487 00001407 D1E6                <1> 	shl	esi, 1
  2488 00001409 668B96[46610000]    <1> 	mov	dx, [esi+cursor_posn]
  2489 00001410 7409                <1> 	jz	short p21
  2490                              <1> 	;xor	si, si
  2491                              <1> 	; 02/02/2022
  2492 00001412 31F6                <1> 	xor	esi, esi
  2493                              <1> p20:
  2494                              <1> 	;add	si, [CRT_LEN]
  2495 00001414 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2496 00001419 E2F9                <1> 	loop	p20
  2497                              <1> p21:
  2498 0000141B 6621D2              <1> 	and	dx, dx
  2499 0000141E 7407                <1> 	jz	short p22
  2500 00001420 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2501 00001425 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2502                              <1> p22:	
  2503                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2504                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2505                              <1> 	;add	dx, 6	; point at status port
  2506 00001427 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2507                              <1> 	; cx = 0
  2508 0000142B C3                  <1> 	retn
  2509                              <1> 
  2510                              <1> scroll_up:
  2511                              <1> 	; 02/02/2022 (simplified scroll up)
  2512                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2513                              <1> 	; 16/01/2016
  2514                              <1> 	; 07/09/2014
  2515                              <1> 	; 02/09/2014
  2516                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2517                              <1> 	; 04/04/2014
  2518                              <1> 	; 04/12/2013
  2519                              <1> 	;
  2520                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2521                              <1> 	;
  2522                              <1> 	; SCROLL UP
  2523                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2524                              <1> 	;	ON THE SCREEN
  2525                              <1> 	; INPUT
  2526                              <1> 	;	(AH) = CURRENT CRT MODE
  2527                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2528                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2529                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2530                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2531                              <1> 	;	(DS) = DATA SEGMENT
  2532                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2533                              <1> 	; OUTPUT
  2534                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2535                              <1> 	;
  2536                              <1> 	;	bh = 0  (02/09/2014)
  2537                              <1> 	;
  2538                              <1> 	; ((ah = 3))
  2539                              <1> 	; cl = left upper column
  2540                              <1> 	; ch = left upper row
  2541                              <1> 	; dl = right lower column
  2542                              <1> 	; dh = right lower row
  2543                              <1> 	;
  2544                              <1> 	; al = line count 
  2545                              <1> 	; ah = attribute to be used on blanked line
  2546                              <1> 	; bl = video page number (0 to 7)
  2547                              <1> 	; 
  2548                              <1> 
  2549                              <1> 	; 02/02/2022 'scroll_up' code
  2550                              <1> 	; ------------------------------------------------------
  2551                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2552                              <1> 
  2553                              <1> 	; INPUT:
  2554                              <1> 	;		
  2555                              <1> 	; al = line count 
  2556                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2557                              <1> 	; ah = attribute to be used on blanked line
  2558                              <1> 	; bl = video page number (0 to 7)
  2559                              <1> 
  2560                              <1> 	;cli
  2561 0000142C 31C9                <1> 	xor	ecx, ecx
  2562 0000142E 88C1                <1> 	mov	cl, al ; line count (cl)
  2563 00001430 BE00800B00          <1> 	mov	esi, 0B8000h
  2564 00001435 3A1D[56610000]      <1> 	cmp	bl, [active_page]
  2565 0000143B 7411                <1> 	je	short n1
  2566 0000143D 20DB                <1> 	and	bl, bl
  2567 0000143F 7422                <1> 	jz	short n3
  2568 00001441 88DD                <1> 	mov	ch, bl ; video page number
  2569                              <1> n0:
  2570 00001443 6681C6A00F          <1> 	add	si, 25*80*2
  2571 00001448 FECD                <1> 	dec	ch
  2572 0000144A 75F7                <1> 	jnz	short n0
  2573 0000144C EB15                <1> 	jmp	short n3
  2574                              <1> n1:
  2575 0000144E 660335[44610000]    <1> 	add	si, [CRT_START]
  2576                              <1> 	;
  2577 00001455 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2578                              <1> n2:			 ; wait_display_enable
  2579 00001459 EC                  <1> 	in	al, dx	 ; get port
  2580 0000145A A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2581 0000145C 74FB                <1> 	jz	short n2 ; wait_display_enable
  2582 0000145E B025                <1> 	mov	al, 25h
  2583 00001460 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2584 00001462 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2585                              <1> n3:
  2586                              <1> 	; cl = line count
  2587                              <1> 	; ah = attribute/color
  2588 00001463 89F7                <1> 	mov	edi, esi
  2589 00001465 20C9                <1> 	and	cl, cl
  2590 00001467 741F                <1> 	jz	short n6
  2591 00001469 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2592 0000146E 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2593 00001472 F366A5              <1> 	rep	movsw
  2594 00001475 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2595                              <1> n4:
  2596                              <1> 	; ah = character attribute/cocor
  2597 00001477 B020                <1> 	mov	al, 20h ; fill with blanks
  2598 00001479 F366AB              <1> 	rep	stosw
  2599                              <1> 
  2600 0000147C 3A1D[56610000]      <1> 	cmp	bl, [active_page]
  2601 00001482 7503                <1> 	jne	short n5
  2602                              <1> 
  2603                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2604 00001484 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2605                              <1> 	;mov	dx, 03D8h ; always set color card port
  2606 00001486 EE                  <1> 	out	dx, al
  2607                              <1> n5:
  2608 00001487 C3                  <1> 	retn
  2609                              <1> n6:
  2610                              <1> 	; clear video page
  2611 00001488 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2612 0000148C EBE9                <1> 	jmp	short n4
  2613                              <1> 
  2614                              <1> 	; 26/02/2022
  2615                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2616                              <1> 	; ------------------------------------------------------
  2617                              <1> 
  2618                              <1> 	; Test	Line Count
  2619                              <1> 	or	al, al
  2620                              <1> 	jz	short al_set
  2621                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2622                              <1> 	sub	bh, ch
  2623                              <1> 	inc	bh	; adjust difference by 1
  2624                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2625                              <1> 	jne	short al_set ; if not the we're all set
  2626                              <1> 	xor	al, al	; otherwise set al to zero
  2627                              <1> al_set:
  2628                              <1> 	xor	bh, bh	; 0
  2629                              <1> 	;push	ax
  2630                              <1> 	push	eax ; 26/02/2022
  2631                              <1> 	;mov 	esi, [crt_base]
  2632                              <1>         mov     esi, 0B8000h  
  2633                              <1>         cmp     bl, [active_page]
  2634                              <1> 	jne	short n0
  2635                              <1> 	;
  2636                              <1>         mov     ax, [CRT_START]
  2637                              <1>         add     si, ax
  2638                              <1>         jmp     short n1
  2639                              <1> n0:
  2640                              <1>         and     bl, bl
  2641                              <1> 	jz	short n1
  2642                              <1> 	mov	al, bl
  2643                              <1> n0x:
  2644                              <1>         ;add    si, [CRT_LEN]
  2645                              <1>         ;add    esi, 80*25*2 
  2646                              <1>         add     si, 80*25*2
  2647                              <1>         dec	al
  2648                              <1> 	jnz	short n0x
  2649                              <1> n1:	
  2650                              <1>         ; Scroll position
  2651                              <1> 	;push	dx ; 26/02/2022
  2652                              <1> 	mov	dx, cx	; now, upper left position in DX
  2653                              <1> 	call	position
  2654                              <1> 	add	esi, eax
  2655                              <1> 	mov	edi, esi
  2656                              <1> 	;pop	dx	; lower right position in DX
  2657                              <1> 	sub	dx, cx
  2658                              <1> 	inc	dh	; dh = #rows 
  2659                              <1> 	inc	dl	; dl = #cols in block
  2660                              <1> 	;pop	ax	; al = line count, ah = attribute
  2661                              <1> 	pop	eax ; 26/02/2022
  2662                              <1> 	xor	ecx, ecx
  2663                              <1> 	mov	cx, ax
  2664                              <1> 	;mov	ah, [CRT_COLS]
  2665                              <1> 	mov	ah, 80
  2666                              <1> 	mul	ah	; determine offset to from address
  2667                              <1> 	add	ax, ax  ; *2 for attribute byte
  2668                              <1> 	;
  2669                              <1> 	;push	ax	; offset 
  2670                              <1> 	;push	dx
  2671                              <1> 	; 26/02/2022
  2672                              <1> 	push	eax
  2673                              <1> 	push	edx
  2674                              <1> 	;
  2675                              <1> 	; 04/04/2014
  2676                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2677                              <1> n8:                      ; wait_display_enable
  2678                              <1>         in      al, dx   ; get port
  2679                              <1> 	test	al, RVRT ; wait for vertical retrace
  2680                              <1> 	jz	short n8 ; wait_display_enable
  2681                              <1> 	mov	al, 25h
  2682                              <1> 	mov	dl, 0D8h ; address control port
  2683                              <1> 	out	dx, al	; turn off video during vertical retrace
  2684                              <1> 	;pop	dx	; #rows, #cols
  2685                              <1>        	;pop	ax	; offset
  2686                              <1> 	; 26/02/2022
  2687                              <1> 	pop	edx
  2688                              <1> 	pop	eax
  2689                              <1> 	xchg	ax, cx	; 
  2690                              <1> 	; ecx = offset, al = line count, ah = attribute
  2691                              <1> ;n9:
  2692                              <1> 	or	al, al
  2693                              <1>         jz      short n3 
  2694                              <1>         add     esi, ecx ; from address for scroll
  2695                              <1> 	mov	bh, dh  ; #rows in block
  2696                              <1> 	sub	bh, al	; #rows to be moved
  2697                              <1> n2:
  2698                              <1> 	; Move rows
  2699                              <1> 	mov	cl, dl	; get # of cols to move
  2700                              <1> 	push	esi
  2701                              <1> 	push	edi	; save start address
  2702                              <1> n10:
  2703                              <1> 	movsw		; move that line on screen
  2704                              <1> 	dec	cl
  2705                              <1>         jnz     short n10
  2706                              <1> 	pop	edi
  2707                              <1> 	pop	esi	; recover addresses
  2708                              <1>         ;mov    cl, [CRT_COLS] 
  2709                              <1> 	;add	cl, cl
  2710                              <1>         ;mov    ecx, 80*2
  2711                              <1>         mov     cx, 80*2
  2712                              <1>         add     esi, ecx  ; next line
  2713                              <1>         add     edi, ecx
  2714                              <1> 	dec	bh	 ; count of lines to move
  2715                              <1> 	jnz	short n2 ; row loop
  2716                              <1> 	; bh = 0
  2717                              <1> 	mov	dh, al	 ; #rows	
  2718                              <1> n3:
  2719                              <1> 	; attribute in ah
  2720                              <1> 	mov	al, ' '	 ; fill with blanks
  2721                              <1> n3x:
  2722                              <1> 	; Clear rows
  2723                              <1>                 ; dh =  #rows
  2724                              <1>         mov	cl, dl	; get # of cols to clear
  2725                              <1>         push    edi     ; save address
  2726                              <1> n11:
  2727                              <1>         stosw           ; store fill character
  2728                              <1> 	dec	cl
  2729                              <1>         jnz     short n11
  2730                              <1>         pop     edi     ; recover address
  2731                              <1> 	;mov	cl, [CRT_COLS]
  2732                              <1> 	;add	cl, cl
  2733                              <1>         ;mov    ecx, 80*2
  2734                              <1>         mov	cl, 80*2
  2735                              <1>         add     edi, ecx
  2736                              <1> 	dec	dh
  2737                              <1> 	jnz	short n3x ; 16/01/2016
  2738                              <1> 	;
  2739                              <1> 	cmp	bl, [active_page]
  2740                              <1> 	jne	short n6
  2741                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2742                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2743                              <1> 	mov	dx, 03D8h ; always set color card port
  2744                              <1> 	out	dx, al
  2745                              <1> n6:
  2746                              <1> 	retn
  2747                              <1> 
  2748                              <1> %endif
  2749                              <1> 
  2750                              <1> write_c_current:
  2751                              <1> 	; 02/02/2022
  2752                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2753                              <1> 	; 18/01/2014
  2754                              <1> 	; 04/12/2013
  2755                              <1> 	;
  2756                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2757                              <1> 	;
  2758                              <1> 	; WRITE_C_CURRENT
  2759                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2760                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2761                              <1> 	; INPUT	
  2762                              <1> 	;	(AH) = CURRENT CRT MODE
  2763                              <1> 	;	(BH) = DISPLAY PAGE
  2764                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2765                              <1> 	;	(AL) = CHAR TO WRITE
  2766                              <1> 	;	(DS) = DATA SEGMENT
  2767                              <1> 	;	(ES) = REGEN SEGMENT
  2768                              <1> 	; OUTPUT
  2769                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2770                              <1> 
  2771 0000148E FA                  <1> 	cli		
  2772                              <1> 	; bl = video page
  2773                              <1> 	; al = character
  2774                              <1> 	; ah = color/attribute
  2775                              <1> 	;push	dx
  2776                              <1> 	;push	ax	; save character & attribute/color
  2777                              <1> 	; 02/02/2022
  2778 0000148F 52                  <1> 	push	edx
  2779 00001490 50                  <1> 	push	eax
  2780 00001491 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2781                              <1> 	; esi = regen location
  2782                              <1> 	; dx = status port
  2783                              <1> 	;
  2784                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2785                              <1> 	;
  2786                              <1> p41:			; wait for horizontal retrace is low or vertical
  2787 00001496 FB                  <1> 	sti		; enable interrupts first
  2788 00001497 3A1D[56610000]      <1>         cmp     bl, [active_page]
  2789 0000149D 7510                <1> 	jne	short p44 
  2790 0000149F FA                  <1> 	cli 		; block interrupts for single loop
  2791 000014A0 EC                  <1> 	in	al, dx	; get status from the adapter
  2792 000014A1 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2793 000014A3 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2794 000014A5 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2795 000014A7 75ED                <1> 	jnz	short p41 ; wait until it is
  2796                              <1> p42:			; wait for either retrace high
  2797 000014A9 EC                  <1> 	in	al, dx	; get status again
  2798 000014AA A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2799 000014AC 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2800                              <1> p43:	
  2801 000014AE FB                  <1> 	sti
  2802                              <1> p44:
  2803                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2804                              <1> 	; 02/02/2022
  2805 000014AF 58                  <1> 	pop	eax
  2806 000014B0 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2807                              <1> 			; Retro UNIX 386 v1 feature only!
  2808 000014B6 668906              <1> 	mov	[esi], ax
  2809                              <1> 	;pop	dx
  2810                              <1> 	; 02/02/2022
  2811 000014B9 5A                  <1> 	pop	edx
  2812 000014BA C3                  <1> 	retn
  2813                              <1> 
  2814                              <1> %if 0	; 02/02/2022
  2815                              <1> 
  2816                              <1> set_mode:
  2817                              <1> 	; 02/02/2022
  2818                              <1> 	; 16/01/2016
  2819                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2820                              <1> 	;
  2821                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2822                              <1> 
  2823                              <1> ;------------------------------------------------------
  2824                              <1> ; SET MODE					      :
  2825                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2826                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2827                              <1> ; INPUT						      :
  2828                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2829                              <1> ; OUTPUT					      :
  2830                              <1> ;	NONE					      :
  2831                              <1> ;------------------------------------------------------
  2832                              <1> 
  2833                              <1> 	push	edi ; 16/01/2016
  2834                              <1> 	push	ebx
  2835                              <1> 	push	edx
  2836                              <1> 	push	ecx ; 16/01/2016
  2837                              <1>         push    eax
  2838                              <1> 
  2839                              <1> 	;mov	dx, 03D4h 	; address or color card
  2840                              <1> 	mov	al, 3
  2841                              <1> ;M8:
  2842                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2843                              <1> 	mov	al, 29h
  2844                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2845                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2846                              <1> 	;push	dx  		; save port value
  2847                              <1> 	;add	dx, 4		; point to control register
  2848                              <1> 	mov	dx, 3D8h
  2849                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2850                              <1> 	;pop	dx
  2851                              <1> ;M9:
  2852                              <1> 	mov	ebx, video_params ; initialization table
  2853                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2854                              <1> 	;xchg 	ah, al
  2855                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2856                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2857                              <1> 	
  2858                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2859                              <1> 	; 02/02/2022
  2860                              <1> 	; dx = 3D8h
  2861                              <1> 	xor	ecx, ecx
  2862                              <1> 	mov	cl, 16
  2863                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2864                              <1> M10:			;  initialization loop
  2865                              <1> 	mov	al, ah 	; get 6845 register number
  2866                              <1> 	out	dx, al
  2867                              <1> 	;inc	dx      ; point to data port
  2868                              <1> 	; 02/02/2022
  2869                              <1> 	inc	dl ; 3D9h
  2870                              <1> 	inc	ah	; next register value
  2871                              <1> 	mov	al, [ebx] ; get table value
  2872                              <1> 	out	dx, al	; out to chip
  2873                              <1> 	inc	ebx	; next in table
  2874                              <1> 	;dec	dx	; back to pointer register
  2875                              <1> 	; 02/02/2022
  2876                              <1> 	dec	dl ; 3D8h
  2877                              <1> 	loop	M10	; do the whole table
  2878                              <1> 	
  2879                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2880                              <1> 	;xor	ax, ax  
  2881                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2882                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2883                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2884                              <1> 	; black background, light gray characeter color, space character
  2885                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2886                              <1> ;M13:			  ; clear buffer
  2887                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2888                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2889                              <1> 
  2890                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2891                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2892                              <1> 			 ; prepare to output to video enable port
  2893                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2894                              <1> 	; 02/02/2022
  2895                              <1> 	;mov	dx, 3D8h
  2896                              <1> 	; 
  2897                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2898                              <1> 	mov	al, 29h
  2899                              <1> 	out	dx, al	 ; set video enable port
  2900                              <1> 
  2901                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2902                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2903                              <1> 	;
  2904                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2905                              <1> 	;
  2906                              <1> ;-----	SET CURSOR POSITIONS
  2907                              <1> 	;push	edi
  2908                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2909                              <1> 	mov	edi, cursor_posn
  2910                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2911                              <1> 	xor	eax, eax
  2912                              <1> 	rep 	stosd	; fill with zeroes
  2913                              <1> 	;pop	edi
  2914                              <1> 
  2915                              <1> ;-----	SET UP OVERSCAN REGISTER
  2916                              <1> 	inc	dx	; set overscan port to a default
  2917                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2918                              <1> ;M14:
  2919                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2920                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2921                              <1> 
  2922                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2923                              <1> 	;
  2924                              <1> 	pop	eax
  2925                              <1> 	pop	ecx ; 16/01/2016
  2926                              <1> 	pop	edx
  2927                              <1> 	pop	ebx
  2928                              <1> 	pop	edi ; 16/01/2016
  2929                              <1> 	retn
  2930                              <1> 
  2931                              <1> %endif
  2932                              <1> 	
  2933                              <1> tty_sw:
  2934                              <1> 	; 02/02/2022
  2935                              <1> 	; 30/06/2015
  2936                              <1> 	; 27/06/2015 
  2937                              <1> 	; 07/09/2014
  2938                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2939                              <1> 	;
  2940                              <1> 	; (Modified registers : EAX)
  2941                              <1> 	;
  2942                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2943                              <1> 	;
  2944                              <1> ;act_disp_page:
  2945                              <1> 	; 30/06/2015
  2946                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2947                              <1> 	; 10/12/2013
  2948                              <1> 	; 04/12/2013
  2949                              <1> 	;
  2950                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2951                              <1> 	;
  2952                              <1> 	; ACT_DISP_PAGE
  2953                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2954                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2955                              <1> 	; INPUT
  2956                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2957                              <1> 	; OUTPUT
  2958                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2959                              <1> 
  2960                              <1> 	;cli
  2961                              <1> 
  2962 000014BB 53                  <1> 	push	ebx
  2963                              <1> 	;push	cx
  2964                              <1> 	;push	dx
  2965                              <1> 	; 02/02/2022
  2966 000014BC 51                  <1> 	push	ecx
  2967 000014BD 52                  <1> 	push	edx
  2968                              <1> 	;
  2969 000014BE A2[56610000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2970                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2971                              <1> 	;mov	cx, 25*80*2
  2972                              <1> 	; 02/02/2022
  2973 000014C3 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2974                              <1> 	; 27/06/2015
  2975 000014C8 0FB6D8              <1> 	movzx	ebx, al
  2976                              <1> 	; 02/02/2022
  2977 000014CB 89D8                <1> 	mov	eax, ebx
  2978                              <1> 	;
  2979                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2980                              <1> 	;mul 	cx	; display page times regen length
  2981                              <1> 	; 02/02/2022
  2982 000014CD F7E1                <1> 	mul	ecx	
  2983                              <1> 	; 10/12/2013
  2984 000014CF 66A3[44610000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2985                              <1> 	;mov	cx, ax	; start address to cx
  2986                              <1> 	; 02/02/2022
  2987 000014D5 89C1                <1> 	mov	ecx, eax
  2988                              <1> 	;sar	cx, 1
  2989                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2990                              <1> 	; 02/02/2022
  2991 000014D7 D1E9                <1> 	shr	ecx, 1
  2992 000014D9 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2993 000014DB E8EFFEFFFF          <1> 	call	m16
  2994                              <1> 	;sal	bx, 1
  2995                              <1> 	; 01/09/2014
  2996 000014E0 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2997 000014E2 81C3[46610000]      <1> 	add	ebx, cursor_posn
  2998 000014E8 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2999 000014EB E8CDFEFFFF          <1> 	call	m18
  3000                              <1> 	;
  3001                              <1> 	;pop	dx
  3002                              <1> 	;pop	cx
  3003                              <1> 	; 02/02/2022
  3004 000014F0 5A                  <1> 	pop	edx
  3005 000014F1 59                  <1> 	pop	ecx
  3006 000014F2 5B                  <1> 	pop	ebx
  3007                              <1> 	;
  3008                              <1> 	;sti
  3009                              <1> 	;
  3010 000014F3 C3                  <1> 	retn
  3011                              <1> 
  3012                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  3013                              <1> 
  3014                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1894                                  
  1895                                  setup_rtc_int:
  1896                                  ; source: http://wiki.osdev.org/RTC
  1897 000014F4 FA                      	cli		; disable interrupts
  1898                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1899                                  	; in order to change this ...
  1900                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1901                                  	; (rate must be above 2 and not over 15)
  1902                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1903 000014F5 B08A                    	mov	al, 8Ah 
  1904 000014F7 E670                    	out	70h, al ; set index to register A, disable NMI
  1905 000014F9 90                      	nop
  1906 000014FA E471                    	in	al, 71h ; get initial value of register A
  1907 000014FC 88C4                    	mov 	ah, al
  1908 000014FE 80E4F0                  	and	ah, 0F0h
  1909 00001501 B08A                    	mov	al, 8Ah 
  1910 00001503 E670                    	out	70h, al ; reset index to register A
  1911 00001505 88E0                    	mov	al, ah
  1912 00001507 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1913 00001509 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1914                                  	; enable RTC interrupt
  1915 0000150B B08B                    	mov	al, 8Bh ;
  1916 0000150D E670                    	out	70h, al ; select register B and disable NMI
  1917 0000150F 90                      	nop
  1918 00001510 E471                    	in	al, 71h ; read the current value of register B
  1919 00001512 88C4                    	mov	ah, al  ;
  1920 00001514 B08B                    	mov 	al, 8Bh ;
  1921 00001516 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1922 00001518 88E0                    	mov	al, ah  ;
  1923 0000151A 0C40                    	or	al, 40h ;
  1924 0000151C E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1925 0000151E FB                      	sti
  1926 0000151F C3                      	retn
  1927                                  
  1928                                  ; Write memory information
  1929                                  ; Temporary Code
  1930                                  ; 06/11/2014
  1931                                  ; 14/08/2015 
  1932                                  memory_info:	
  1933 00001520 A1[2C610000]            	mov	eax, [memory_size] ; in pages
  1934 00001525 50                      	push	eax
  1935 00001526 C1E00C                  	shl	eax, 12		   ; in bytes
  1936 00001529 BB0A000000              	mov	ebx, 10
  1937 0000152E 89D9                    	mov	ecx, ebx	   ; 10
  1938 00001530 BE[955D0000]            	mov	esi, mem_total_b_str	
  1939 00001535 E8AE000000              	call	bintdstr
  1940 0000153A 58                      	pop	eax
  1941 0000153B B107                    	mov	cl, 7
  1942 0000153D BE[B95D0000]            	mov	esi, mem_total_p_str
  1943 00001542 E8A1000000              	call	bintdstr	
  1944                                  	; 14/08/2015
  1945 00001547 E8B9000000              	call	calc_free_mem
  1946                                  	; edx = calculated free pages
  1947                                  	; ecx = 0
  1948 0000154C A1[30610000]            	mov 	eax, [free_pages]
  1949 00001551 39D0                    	cmp	eax, edx ; calculated free mem value 
  1950                                  		; and initial free mem value are same or not?
  1951 00001553 751D                    	jne 	short pmim ; print mem info with '?' if not
  1952 00001555 52                      	push 	edx ; free memory in pages	
  1953                                  	;mov 	eax, edx
  1954 00001556 C1E00C                  	shl	eax, 12 ; convert page count
  1955                                  			; to byte count
  1956 00001559 B10A                    	mov	cl, 10
  1957 0000155B BE[D95D0000]            	mov	esi, free_mem_b_str
  1958 00001560 E883000000              	call	bintdstr
  1959 00001565 58                      	pop	eax
  1960 00001566 B107                    	mov	cl, 7
  1961 00001568 BE[FD5D0000]            	mov	esi, free_mem_p_str
  1962 0000156D E876000000              	call	bintdstr
  1963                                  pmim:
  1964 00001572 BE[835D0000]            	mov	esi, msg_memory_info
  1965                                  pmim_nb:	
  1966 00001577 AC                      	lodsb
  1967 00001578 08C0                    	or	al, al
  1968 0000157A 740D                    	jz	short pmim_ok
  1969 0000157C 56                      	push	esi
  1970 0000157D 31DB                    	xor	ebx, ebx ; 0
  1971                                  			; Video page 0 (bl=0)
  1972 0000157F B407                    	mov	ah, 07h ; Black background, 
  1973                                  			; light gray forecolor
  1974 00001581 E816FDFFFF              	call	write_tty
  1975 00001586 5E                      	pop	esi
  1976 00001587 EBEE                    	jmp	short pmim_nb
  1977                                  pmim_ok:
  1978 00001589 C3                      	retn
  1979                                  
  1980                                  ; Convert binary number to hexadecimal string
  1981                                  ; 10/05/2015  
  1982                                  ; dsectpm.s (28/02/2015)
  1983                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1984                                  ; 01/12/2014
  1985                                  ; 25/11/2014
  1986                                  ;
  1987                                  bytetohex:
  1988                                  	; INPUT ->
  1989                                  	; 	AL = byte (binary number)
  1990                                  	; OUTPUT ->
  1991                                  	;	AX = hexadecimal string
  1992                                  	;
  1993 0000158A 53                      	push	ebx
  1994 0000158B 31DB                    	xor	ebx, ebx
  1995 0000158D 88C3                    	mov	bl, al
  1996 0000158F C0EB04                  	shr	bl, 4
  1997 00001592 8A9B[D8150000]          	mov	bl, [ebx+hexchrs]
  1998 00001598 86D8                    	xchg	bl, al
  1999 0000159A 80E30F                  	and	bl, 0Fh
  2000 0000159D 8AA3[D8150000]          	mov	ah, [ebx+hexchrs]
  2001 000015A3 5B                      	pop	ebx	
  2002 000015A4 C3                      	retn
  2003                                  
  2004                                  wordtohex:
  2005                                  	; INPUT ->
  2006                                  	; 	AX = word (binary number)
  2007                                  	; OUTPUT ->
  2008                                  	;	EAX = hexadecimal string
  2009                                  	;
  2010 000015A5 53                      	push	ebx
  2011 000015A6 31DB                    	xor	ebx, ebx
  2012 000015A8 86E0                    	xchg	ah, al
  2013 000015AA 6650                    	push	ax
  2014 000015AC 88E3                    	mov	bl, ah
  2015 000015AE C0EB04                  	shr	bl, 4
  2016 000015B1 8A83[D8150000]          	mov	al, [ebx+hexchrs]
  2017 000015B7 88E3                    	mov	bl, ah
  2018 000015B9 80E30F                  	and	bl, 0Fh
  2019 000015BC 8AA3[D8150000]          	mov	ah, [ebx+hexchrs]
  2020 000015C2 C1E010                  	shl	eax, 16
  2021 000015C5 6658                    	pop	ax
  2022 000015C7 5B                      	pop	ebx
  2023 000015C8 EBC0                    	jmp	short bytetohex
  2024                                  	;mov	bl, al
  2025                                  	;shr	bl, 4
  2026                                  	;mov	bl, [ebx+hexchrs]
  2027                                  	;xchg	bl, al	 	
  2028                                  	;and	bl, 0Fh
  2029                                  	;mov	ah, [ebx+hexchrs]
  2030                                  	;pop	ebx	
  2031                                  	;retn
  2032                                  
  2033                                  dwordtohex:
  2034                                  	; INPUT ->
  2035                                  	; 	EAX = dword (binary number)
  2036                                  	; OUTPUT ->
  2037                                  	;	EDX:EAX = hexadecimal string
  2038                                  	;
  2039 000015CA 50                      	push	eax
  2040 000015CB C1E810                  	shr	eax, 16
  2041 000015CE E8D2FFFFFF              	call	wordtohex
  2042 000015D3 89C2                    	mov	edx, eax
  2043 000015D5 58                      	pop	eax
  2044                                  	;call	wordtohex
  2045                                  	;retn
  2046                                  	; 02/01/2022
  2047 000015D6 EBCD                    	jmp	short wordtohex
  2048                                  
  2049                                  ; 10/05/2015
  2050                                  hex_digits:
  2051                                  hexchrs:
  2052 000015D8 303132333435363738-     	db '0123456789ABCDEF'
  2052 000015E1 39414243444546     
  2053                                  
  2054                                  ; Convert binary number to decimal/numeric string
  2055                                  ; 06/11/2014
  2056                                  ; Temporary Code
  2057                                  ;
  2058                                  
  2059                                  bintdstr:
  2060                                  	; EAX = binary number
  2061                                  	; ESI = decimal/numeric string address
  2062                                  	; EBX = divisor (10)
  2063                                  	; ECX = string length (<=10)
  2064 000015E8 01CE                    	add	esi, ecx
  2065                                  btdstr0:
  2066 000015EA 4E                      	dec	esi
  2067 000015EB 31D2                    	xor	edx, edx
  2068 000015ED F7F3                    	div	ebx
  2069 000015EF 80C230                  	add	dl, 30h
  2070 000015F2 8816                    	mov	[esi], dl
  2071 000015F4 FEC9                    	dec	cl
  2072 000015F6 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2073 000015F8 09C0                    	or	eax, eax
  2074 000015FA 75EE                    	jnz	short btdstr0
  2075                                  btdstr1:
  2076 000015FC 4E                      	dec	esi
  2077 000015FD C60620                          mov     byte [esi], 20h ; blank space
  2078 00001600 FEC9                    	dec	cl
  2079 00001602 75F8                    	jnz	short btdstr1
  2080                                  btdstr2:
  2081 00001604 C3                      	ret
  2082                                  
  2083                                  ; Calculate free memory pages on M.A.T.
  2084                                  ; 06/11/2014
  2085                                  ; Temporary Code
  2086                                  ;
  2087                                  
  2088                                  calc_free_mem:
  2089 00001605 31D2                    	xor	edx, edx
  2090                                  	;xor	ecx, ecx
  2091                                  	;mov	cx, [mat_size] ; in pages
  2092                                  	; 02/01/2022
  2093 00001607 8B0D[40610000]          	mov	ecx, [mat_size] ; in pages
  2094 0000160D C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2095 00001610 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2096                                  cfm0:
  2097 00001615 AD                      	lodsd
  2098 00001616 51                      	push	ecx
  2099 00001617 B920000000              	mov	ecx, 32
  2100                                  cfm1:
  2101 0000161C D1E8                    	shr	eax, 1
  2102 0000161E 7301                    	jnc	short cfm2
  2103 00001620 42                      	inc	edx
  2104                                  cfm2:
  2105 00001621 E2F9                    	loop	cfm1
  2106 00001623 59                      	pop	ecx
  2107 00001624 E2EF                    	loop	cfm0
  2108 00001626 C3                      	ret
  2109                                  
  2110                                  %include 'diskio.inc'  ; 07/03/2015
  2111                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.6) - DISKIO.INC
  2112                              <1> ; Last Modification: 18/07/2022
  2113                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2114                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2115                              <1> 
  2116                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2117                              <1> 
  2118                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2119                              <1> 
  2120                              <1> ; 11/07/2022
  2121                              <1> ;; 06/02/2015
  2122                              <1> ;diskette_io:
  2123                              <1> ;	pushfd
  2124                              <1> ;	push 	cs
  2125                              <1> ;	call 	DISKETTE_IO_1
  2126                              <1> ;	retn
  2127                              <1> 	
  2128                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2129                              <1> ;//////////////////////////////////////////////////////
  2130                              <1> 
  2131                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2132                              <1> ;		Function in AL
  2133                              <1> ;			0 = reset
  2134                              <1> ;			1 = read
  2135                              <1> ;			2 = write
  2136                              <1> ;		Disk drive number in DL
  2137                              <1> ;			0 & 1 = floppy disks	
  2138                              <1> ;			80h .. 83h = hard disks
  2139                              <1> ;		Sector address (LBA) in ECX
  2140                              <1> ;		Buffer address in EBX
  2141                              <1> ;		R/W sector count is (always) 1
  2142                              <1> ;
  2143                              <1> ;		Return:
  2144                              <1> ;			Status in AH (>0 = error code)
  2145                              <1> ;			if CF = 1 -> error code in AH
  2146                              <1> ;			if CF = 0 -> successful
  2147                              <1> ;			AL = undefined
  2148                              <1> ;
  2149                              <1> ;		Modified registers: (only) EAX
  2150                              <1> 
  2151                              <1> ; 10/07/2022
  2152                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2153                              <1> ;		by removing unused IBM PC-AT disk functions)
  2154                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2155                              <1> ; 20/02/2015
  2156                              <1> ; 06/02/2015 (unix386.s)
  2157                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2158                              <1> ;
  2159                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2160                              <1> ;
  2161                              <1> ; ADISK.EQU
  2162                              <1> 
  2163                              <1> ;----- Wait control constants 
  2164                              <1> 
  2165                              <1> ;amount of time to wait while RESET is active.
  2166                              <1> 
  2167                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2168                              <1> 					;at 250 KBS xfer rate.
  2169                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2170                              <1> 
  2171                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2172                              <1> 					;status register to become valid
  2173                              <1> 					;before re-reading.
  2174                              <1> 
  2175                              <1> ;After sending a byte to NEC, status register may remain
  2176                              <1> ;incorrectly set for 24 us.
  2177                              <1> 
  2178                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2179                              <1> 					;RQM low.
  2180                              <1> 
  2181                              <1> ; COMMON.MAC
  2182                              <1> ;
  2183                              <1> ;	Timing macros
  2184                              <1> ;
  2185                              <1> 
  2186                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2187                              <1> 		jmp short $+2
  2188                              <1> %endmacro		
  2189                              <1> 
  2190                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2191                              <1> 		jmp short $+2
  2192                              <1> 		jmp short $+2
  2193                              <1> %endmacro
  2194                              <1> 
  2195                              <1> %macro		NEWIODELAY 0
  2196                              <1> 		out 0EBh,al
  2197                              <1> %endmacro 
  2198                              <1> 
  2199                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2200                              <1> ;;; WAIT_FOR_MEM
  2201                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2202                              <1> ;WAIT_FDU_INT_HI	equ	1
  2203                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2204                              <1> ;;; WAIT_FOR_PORT
  2205                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2206                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2207                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2208                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2209                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2210                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2211                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2212                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2213                              <1> ;;; WAIT_REFRESH
  2214                              <1> ;amount of time to wait for head settle, per unit in parameter
  2215                              <1> ;table = 1 ms.
  2216                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2217                              <1> 
  2218                              <1> 
  2219                              <1> ; //////////////// DISKETTE I/O ////////////////
  2220                              <1> 
  2221                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2222                              <1> 
  2223                              <1> ;----------------------------------------
  2224                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2225                              <1> ;----------------------------------------
  2226                              <1> 
  2227                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2228                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2229                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2230                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2231                              <1> 
  2232                              <1> ;----------------------------------------
  2233                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2234                              <1> ;-------------------------------------------------------------------------------
  2235                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2236                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2237                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2238                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2239                              <1> 
  2240                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2241                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2242                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2243                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2244                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2245                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2246                              <1> 
  2247                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2248                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2249                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2250                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2251                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2252                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2253                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2254                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2255                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2256                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2257                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2258                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2259                              <1> 
  2260                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2261                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2262                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2263                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2264                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2265                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2266                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2267                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2268                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2269                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2270                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2271                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2272                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2273                              <1> 
  2274                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2275                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2276                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2277                              <1> 
  2278                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2279                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2280                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2281                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2282                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2283                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2284                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2285                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2286                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2287                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2288                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2289                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2290                              <1> 
  2291                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2292                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2293                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2294                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2295                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2296                              <1> 
  2297                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2298                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2299                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2300                              <1> INTA01		EQU	021H		; 8259 PORT
  2301                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2302                              <1> INTB01		EQU	0A1H		;
  2303                              <1> 
  2304                              <1> ;-------------------------------------------------------------------------------
  2305                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2306                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2307                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2308                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2309                              <1> ;-------------------------------------------------------------------------------
  2310                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2311                              <1> 
  2312                              <1> ;-------------------------------------------------------------------------------
  2313                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2314                              <1> 
  2315                              <1> ; 10/07/2022
  2316                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2317                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2318                              <1> ; (unix386.s <-- dsectrm2.s)
  2319                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2320                              <1> 
  2321                              <1> ; 10/12/2014
  2322                              <1> ;
  2323                              <1> ;int40h:
  2324                              <1> ;	pushf
  2325                              <1> ;	push 	cs
  2326                              <1> ;	;cli
  2327                              <1> ;	call 	DISKETTE_IO_1
  2328                              <1> ;	retn
  2329                              <1> 
  2330                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2331                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2332                              <1> ;
  2333                              <1> 
  2334                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2335                              <1> ; DISKETTE I/O
  2336                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2337                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2338                              <1> ; INPUT
  2339                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2340                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2341                              <1> ;		ON ALL DRIVES
  2342                              <1> ;------------------------------------------------------------------------------- 
  2343                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2344                              <1> ;-------------------------------------------------------------------------------
  2345                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2346                              <1> ;-------------------------------------------------------------------------------
  2347                              <1> ;
  2348                              <1> ;	REGISTERS FOR READ/WRITE
  2349                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2350                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2351                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2352                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2353                              <1> ;		320/360	320/360	    0-39
  2354                              <1> ;		320/360	1.2M	    0-39
  2355                              <1> ;		1.2M	1.2M	    0-79
  2356                              <1> ;		720K	720K	    0-79
  2357                              <1> ;		1.44M	1.44M	    0-79	
  2358                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2359                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2360                              <1> ;		320/360	320/360	     1-8/9
  2361                              <1> ;		320/360	1.2M	     1-8/9
  2362                              <1> ;		1.2M	1.2M	     1-15
  2363                              <1> ;		720K	720K	     1-9
  2364                              <1> ;		1.44M	1.44M	     1-18		
  2365                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2366                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2367                              <1> ;		320/360	320/360	        8/9
  2368                              <1> ;		320/360	1.2M	        8/9
  2369                              <1> ;		1.2M	1.2M		15
  2370                              <1> ;		720K	720K		9
  2371                              <1> ;		1.44M	1.44M		18
  2372                              <1> ;
  2373                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2374                              <1> ;
  2375                              <1> ;-------------------------------------------------------------------------------
  2376                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2377                              <1> ;	AH = STATUS OF OPERATION
  2378                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2379                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2380                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2381                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2382                              <1> ;	FOR READ/WRITE/VERIFY
  2383                              <1> ;		DS,BX,DX,CX PRESERVED
  2384                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2385                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2386                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2387                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2388                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2389                              <1> ;-------------------------------------------------------------------------------
  2390                              <1> ;
  2391                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2392                              <1> ;
  2393                              <1> ;   -----------------------------------------------------------------
  2394                              <1> ;   |       |       |       |       |       |       |       |       |
  2395                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2396                              <1> ;   |       |       |       |       |       |       |       |       |
  2397                              <1> ;   -----------------------------------------------------------------
  2398                              <1> ;	|	|	|	|	|	|	|	|
  2399                              <1> ;	|	|	|	|	|	-----------------
  2400                              <1> ;	|	|	|	|	|		|
  2401                              <1> ;	|	|	|	|    RESERVED		|
  2402                              <1> ;	|	|	|	|		  PRESENT STATE
  2403                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2404                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2405                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2406                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2407                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2408                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2409                              <1> ;	|	|	|	|	110: RESERVED
  2410                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2411                              <1> ;	|	|	|	|
  2412                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2413                              <1> ;	|	|	|
  2414                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2415                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2416                              <1> ;	|	|
  2417                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2418                              <1> ;
  2419                              <1> ;						00: 500 KBS
  2420                              <1> ;						01: 300 KBS
  2421                              <1> ;						10: 250 KBS
  2422                              <1> ;						11: RESERVED
  2423                              <1> ;
  2424                              <1> ;
  2425                              <1> 
  2426                              <1> struc MD
  2427 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2428 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2429 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2430 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2431 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2432 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2433 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2434 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2435 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2436 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2437 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2438 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2439 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2440                              <1> endstruc
  2441                              <1> 
  2442                              <1> BIT7OFF	EQU	7FH
  2443                              <1> BIT7ON	EQU	80H
  2444                              <1> 
  2445                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2446                              <1> ;		Function in AL
  2447                              <1> ;			0 = reset
  2448                              <1> ;			1 = read
  2449                              <1> ;			2 = write
  2450                              <1> ;		Disk drive number in DL
  2451                              <1> ;			0 & 1 = floppy disks	
  2452                              <1> ;			80h .. 83h = hard disks
  2453                              <1> ;		Sector address (LBA) in ECX
  2454                              <1> ;		Buffer address in EBX
  2455                              <1> ;		R/W sector count is (always) 1
  2456                              <1> ;
  2457                              <1> ;		Return:
  2458                              <1> ;			Status in AH (>0 = error code)
  2459                              <1> ;			if CF = 1 -> error code in AH
  2460                              <1> ;			if CF = 0 -> successful
  2461                              <1> ;			AL = undefined
  2462                              <1> ;
  2463                              <1> ;		Modified registers: (only) EAX
  2464                              <1> 
  2465                              <1> ; 11/07/2022
  2466                              <1> ;;int13h: ; 16/02/2015
  2467                              <1> ;; 16/02/2015 - 21/02/2015
  2468                              <1> ;int40h:
  2469                              <1> ;	pushfd
  2470                              <1> ;	push 	cs
  2471                              <1> ;	call 	DISKETTE_IO_1
  2472                              <1> ;	retn	
  2473                              <1> 
  2474                              <1> DISKETTE_IO_1:
  2475                              <1> 
  2476                              <1> 	;sti				; INTERRUPTS BACK ON
  2477                              <1> 	; 11/07/2022
  2478                              <1> 	; save registers
  2479 00001627 55                  <1> 	push	ebp			; ANY
  2480                              <1> 
  2481                              <1> 	; 11/07/2022
  2482                              <1> 	;push	edi			; ANY
  2483                              <1> 	;push	edx			; DRIVE NUMBER (DL)
  2484                              <1> 	;push	ebx			; BUFFER ADDRESS
  2485                              <1> 	;push	ecx			; SECTOR ADDRESS (LBA)
  2486                              <1> 	;push	esi			; ANY
  2487                              <1> 
  2488                              <1> 	; 11/07/2022
  2489 00001628 89DD                <1> 	mov	ebp, ebx ; buffer address
  2490 0000162A C605[AC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS
  2491 00001631 0FB6FA              <1> 	movzx	edi, dl ; drive number (0 or 1)
  2492                              <1> 	
  2493 00001634 08C0                <1> 	or	al, al			; RESET ?
  2494 00001636 7507                <1> 	jnz	short DISKETTE_RW_1	; NO
  2495                              <1> 
  2496 00001638 E84D010000          <1> 	call	DSK_RESET
  2497                              <1> 
  2498 0000163D EB37                <1> 	jmp	short DISKETTE_RW_2	
  2499                              <1> 
  2500                              <1> DISKETTE_RW_1:
  2501                              <1> 	; 12/07/2022
  2502                              <1> 	; 11/07/2022
  2503                              <1> 	; ecx = sector address (LBA, < 2880)
  2504                              <1> 	; ebp = buffer address
  2505                              <1> 	; edi = drive number (0 or 1)
  2506                              <1> 	;  al = function (read = 1 or write = 2)
  2507                              <1> 
  2508 0000163F 88C2                <1> 	mov	dl, al ; *
  2509                              <1> convert_to_chs:
  2510                              <1> 	;;;
  2511 00001641 B004                <1> 	mov	al, 4 ; MD.SEC_TRK ; sector per track (drv.spt)
  2512 00001643 E8D9050000          <1> 	call	GET_PARM
  2513                              <1> 	; 12/07/2022
  2514 00001648 88E6                <1> 	mov	dh, ah ; spt
  2515 0000164A 89C8                <1> 	mov	eax, ecx ; sector address (LBA) 
  2516 0000164C F6F6                <1> 	div	dh  ; AX/DH
  2517 0000164E 88E1                <1> 	mov	cl, ah ; sector number - 1
  2518 00001650 FEC1                <1> 	inc	cl  ; sector number (1 based)
  2519 00001652 28ED                <1> 	sub	ch, ch ; head = 0 
  2520                              <1> 	; heads = 2
  2521 00001654 D0E8                <1> 	shr	al, 1 ; al = al/2
  2522 00001656 80D500              <1> 	adc	ch, 0 ; head = 1 or head = 0
  2523 00001659 C1E110              <1> 	shl	ecx, 16
  2524 0000165C 88C1                <1> 	mov	cl, al ; track (cylinder)
  2525 0000165E 88D5                <1> 	mov	ch, dl ; function number 
  2526 00001660 89CE                <1> 	mov	esi, ecx ; byte 0 = track, byte 1 = function
  2527                              <1> 			 ; byte 2 = sector, byte 3 = head
  2528 00001662 C1C610              <1> 	rol	esi, 16
  2529                              <1> 			 ; byte 0 = sector, byte 1 = head
  2530                              <1> 			 ; byte 2 = track, byte 3 = function		
  2531                              <1> 	;;; 
  2532 00001665 80FA02              <1> 	cmp	dl, 2 ; *
  2533 00001668 7407                <1> 	je	short DISKETTE_W
  2534                              <1> DISKETTE_R:	
  2535                              <1> 	; dl = 1 ; *
  2536 0000166A E809000000          <1> 	call	DSK_READ
  2537 0000166F EB05                <1> 	jmp	short DISKETTE_RW_2
  2538                              <1> DISKETTE_W:
  2539 00001671 E80F000000          <1> 	call	DSK_WRITE
  2540                              <1> DISKETTE_RW_2:
  2541                              <1> 	; 11/07/2022
  2542                              <1> 	; Restore registers
  2543                              <1> 	;pop	esi
  2544                              <1> 	;pop	ecx
  2545                              <1> 	;pop	ebx
  2546                              <1> 	;pop	edx
  2547                              <1> 	;pop	edi
  2548                              <1> 
  2549                              <1> 	; 11/07/2022
  2550 00001676 5D                  <1> 	pop	ebp
  2551 00001677 C3                  <1> 	retn
  2552                              <1> 
  2553                              <1> ;-------------------------------------------------------------------------------
  2554                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2555                              <1> ;	DISKETTE READ.
  2556                              <1> ;
  2557                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2558                              <1> ;		SI-HI	: HEAD #
  2559                              <1> ;		SI-LOW	: # OF SECTORS
  2560                              <1> ;		ES	: BUFFER SEGMENT
  2561                              <1> ;		[BP]	: SECTOR #
  2562                              <1> ;		[BP+1]	: TRACK #
  2563                              <1> ;		[BP+2]	: BUFFER OFFSET
  2564                              <1> ;
  2565                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2566                              <1> ;-------------------------------------------------------------------------------
  2567                              <1> 
  2568                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2569                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2570                              <1> 
  2571                              <1> DSK_READ:
  2572 00001678 8025[AA610000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2573 0000167F 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2574                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2575                              <1> 	;retn
  2576 00001683 EB0B                <1> 	jmp	short RD_WR_VF
  2577                              <1> 
  2578                              <1> ;-------------------------------------------------------------------------------
  2579                              <1> ; DISK_WRITE	(AH = 02H)
  2580                              <1> ;	DISKETTE WRITE.
  2581                              <1> ;
  2582                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2583                              <1> ;		SI-HI	: HEAD #
  2584                              <1> ;		SI-LOW	: # OF SECTORS
  2585                              <1> ;		ES	: BUFFER SEGMENT
  2586                              <1> ;		[BP]	: SECTOR #
  2587                              <1> ;		[BP+1]	: TRACK #
  2588                              <1> ;		[BP+2]	: BUFFER OFFSET
  2589                              <1> ;
  2590                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2591                              <1> ;-------------------------------------------------------------------------------
  2592                              <1> 
  2593                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2594                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2595                              <1> 
  2596                              <1> DSK_WRITE:
  2597 00001685 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2598 00001689 800D[AA610000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2599                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2600                              <1> 	;;retn
  2601                              <1> 	;jmp	short RD_WR_VF
  2602                              <1> 
  2603                              <1> ;-------------------------------------------------------------------------------
  2604                              <1> ; RD_WR_VF
  2605                              <1> ;	COMMON READ, WRITE
  2606                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2607                              <1> ;
  2608                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2609                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2610                              <1> ;
  2611                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2612                              <1> ;-------------------------------------------------------------------------------
  2613                              <1> 
  2614                              <1> RD_WR_VF:
  2615                              <1> 	; 18/07/2022
  2616                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2617 00001690 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2618 00001691 E8C9010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2619 00001696 E82B020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2620 0000169B 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2621                              <1> DO_AGAIN:
  2622 0000169C 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2623 0000169D E865020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2624 000016A2 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2625                              <1> 	; 24/12/2021
  2626 000016A3 7305                <1> 	jnc	short RWV
  2627 000016A5 E9B6000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2628                              <1> RWV:
  2629 000016AA 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2630 000016AB 8AB7[B7610000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2631 000016B1 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2632 000016B4 E85F050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2633                              <1> 	; 20/02/2015
  2634 000016B9 7445                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2635 000016BB 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2636 000016BD 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2637 000016BF F687[B7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2638 000016C6 740F                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2639                              <1> 	;mov	al, 2			; CHANGE TO 1.2M
  2640                              <1> 	; 12/07/2022
  2641 000016C8 FEC0                <1> 	inc	al  ; al = 2
  2642 000016CA EB0B                <1> 	jmp	short RWV_2
  2643                              <1> RWV_1:
  2644                              <1> 	; 12/07/2022
  2645                              <1> 	;jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2646 000016CC F687[B7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2647 000016D3 7502                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2648 000016D5 B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2649                              <1> 	; 12/07/2022
  2650                              <1> 	;jmp	short RWV_3
  2651                              <1> RWV_2:
  2652                              <1> 	; 12/07/2022
  2653                              <1> 	;or	al, al			; TEST FOR NO DRIVE
  2654                              <1> 	;jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2655                              <1> RWV_3:
  2656                              <1> 	; 12/07/2022
  2657                              <1> 	;mov	dl, al	; 11/07/2022
  2658 000016D7 E81F010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2659 000016DC 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2660                              <1> 
  2661                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2662                              <1> 
  2663 000016DE 57                  <1> 	push	edi			; SAVE DRIVE #
  2664                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2665 000016DF BB[CC5B0000]        <1> 	mov	ebx, DR_TYPE
  2666                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2667 000016E4 B106                <1> 	mov	cl, DR_CNT
  2668                              <1> RWV_DR_SEARCH:
  2669                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2670 000016E6 8A23                <1> 	mov	ah, [ebx]
  2671 000016E8 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2672 000016EB 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2673                              <1> 	; 12/07/2022
  2674                              <1> 	;cmp	dl, ah ; 11/07/2022
  2675 000016ED 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2676                              <1> RWV_DR_FND:
  2677                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2678 000016EF 43                  <1> 	inc	ebx
  2679 000016F0 8B3B                <1> 	mov	edi, [ebx]
  2680 000016F2 4B                  <1> 	dec	ebx
  2681                              <1> RWV_MD_SEARH:
  2682 000016F3 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2683 000016F6 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2684                              <1> RWV_NXT_MD:
  2685 000016F8 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2686                              <1> 	;loop	RWV_DR_SEARCH
  2687 000016FB FEC9                <1> 	dec	cl
  2688 000016FD 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2689 000016FF 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2690                              <1> 
  2691                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2692                              <1> 
  2693                              <1> RWV_ASSUME:
  2694 00001700 BB[EA5B0000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2695 00001705 F687[B7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2696 0000170C 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2697 0000170E BB[045C0000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2698 00001713 EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2699                              <1> 
  2700                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2701                              <1> 	 			
  2702                              <1> RWV_MD_FND:
  2703 00001715 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2704 00001717 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2705                              <1> 	
  2706                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2707                              <1> 
  2708                              <1> RWV_MD_FND1:
  2709 00001718 E824010000          <1> 	call	SEND_SPEC_MD
  2710 0000171D E851020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2711 00001722 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2712 00001724 E82C020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2713                              <1> RWV_DBL:
  2714 00001729 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2715 0000172A E847040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2716 0000172F 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2717 00001730 7221                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2718                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2719                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2720                              <1> 	; 08/07/2022
  2721 00001732 8B0424              <1> 	mov	eax, [esp]
  2722                              <1> 	; 18/07/2022
  2723                              <1> 	;push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2724 00001735 E84C020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2725                              <1> 	;pop	ebx
  2726 0000173A 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2727 0000173B 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2728 0000173D 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2729 0000173E 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2730 0000173F E88C020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2731 00001744 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2732 00001745 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2733 00001747 E8B5020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2734 0000174C 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2735 0000174E E8FC020000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2736                              <1> CHK_RET:
  2737 00001753 E89B030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2738 00001758 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2739 00001759 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2740 0000175B E93CFFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2741                              <1> RWV_END:
  2742 00001760 E846030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2743 00001765 E8D7030000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2744                              <1> RWV_BAC:
  2745                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2746                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2747                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2748                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2749                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2750                              <1> 	;;retn
  2751                              <1> 	;jmp	SETUP_END
  2752                              <1> 
  2753                              <1> ;-------------------------------------------------------------------------------
  2754                              <1> ; SETUP_END
  2755                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2756                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2757                              <1> ;
  2758                              <1> ; ON EXIT:
  2759                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2760                              <1> ;-------------------------------------------------------------------------------
  2761                              <1> SETUP_END:
  2762                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2763                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2764                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2765 0000176A 50                  <1> 	push	eax ; 24/12/2021
  2766 0000176B B002                <1> 	mov	al, 2 ; 08/07/2022
  2767 0000176D E8AF040000          <1> 	call	GET_PARM
  2768 00001772 8825[AB610000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2769                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2770 00001778 58                  <1> 	pop	eax ; 24/12/2021
  2771 00001779 8A25[AC610000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2772 0000177F 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2773 00001781 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2774 00001783 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2775                              <1> ;NUN_ERR: 
  2776 00001785 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2777 00001788 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2778                              <1> NUN_ERR:
  2779 00001789 C3                  <1> 	retn
  2780                              <1> 
  2781                              <1> ;-------------------------------------------------------------------------------
  2782                              <1> ; DISK_RESET	(AH = 00H)	
  2783                              <1> ;		RESET THE DISKETTE SYSTEM.
  2784                              <1> ;
  2785                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2786                              <1> ;-------------------------------------------------------------------------------
  2787                              <1> DSK_RESET:
  2788                              <1> 	; 17/07/2022
  2789                              <1> 	; 12/07/2022
  2790                              <1> 	; 11/07/2022
  2791                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2792 0000178A 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2793 0000178E FA                  <1> 	cli				; NO INTERRUPTS
  2794 0000178F A0[AA610000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2795 00001794 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2796 00001796 C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2797                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2798 00001799 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2799 0000179B EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2800 0000179C C605[A9610000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2801                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2802                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2803                              <1> 					;      PULSE WIDTH)
  2804                              <1> 	; 19/12/2014
  2805                              <1> 	NEWIODELAY
  2196 000017A3 E6EB                <2>  out 0EBh,al
  2806                              <1> 
  2807                              <1> 	; 17/12/2014 
  2808                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2809 000017A5 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2810                              <1> wdw1:
  2811                              <1> 	NEWIODELAY   ; 27/02/2015
  2196 000017AA E6EB                <2>  out 0EBh,al
  2812 000017AC E2FC                <1> 	loop	wdw1
  2813                              <1> 	;
  2814 000017AE 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2815 000017B0 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2816                              <1> 	; 16/12/2014
  2817                              <1> 	IODELAY
  2191 000017B1 EB00                <2>  jmp short $+2
  2192 000017B3 EB00                <2>  jmp short $+2
  2818                              <1> 	;
  2819                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2820 000017B5 E862060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2821 000017BA 7236                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2822                              <1> 	;mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2823                              <1> 	; 12/07/2022
  2824                              <1> 	;xor	ecx, ecx
  2825                              <1> 	; 17/07/2022
  2826                              <1> 	;xor	ch, ch
  2827 000017BC B1C0                <1> 	mov	cl, 11000000b
  2828                              <1> NXT_DRV:
  2829                              <1> 	; 24/12/2021
  2830 000017BE 51                  <1> 	push	ecx			; SAVE FOR CALL
  2831 000017BF B8[F1170000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2832 000017C4 50                  <1> 	push	eax			;
  2833 000017C5 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2834 000017C7 E846050000          <1> 	call	NEC_OUTPUT
  2835 000017CC 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2836 000017CD E879060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2837                              <1> 	; 24/12/2021
  2838 000017D2 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2839 000017D3 721D                <1> 	jc	short DR_ERR		; ERROR RETURN
  2840 000017D5 3A0D[AD610000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2841 000017DB 7515                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2842 000017DD FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2843 000017DF 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2844 000017E2 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2845                              <1> 	;
  2846 000017E4 E82F000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2847                              <1> RESBAC:
  2848 000017E9 E87CFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2849                              <1> 	
  2850                              <1> 	; 11/07/2022
  2851                              <1> 	; CF = 1 -> error (error code in AH)
  2852                              <1> 	; CF = 0 -> OK
  2853                              <1> 	
  2854                              <1> 	;; 24/12/2021
  2855                              <1> 	;mov	ebx, esi		; GET SAVED AL TO BL
  2856                              <1> 	;; 11/07/2022
  2857                              <1> 	;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 
  2858                              <1> 	;rol	ebx, 8
  2859                              <1> 	; bl = function (reset = 0)
  2860                              <1> 	;
  2861                              <1> 	;mov	al, bl			; PUT BACK FOR RETURN
  2862                              <1> 	
  2863                              <1> 	; 11/07/2022  
  2864 000017EE B000                <1> 	mov	al, 0	; (reset function = 0)
  2865                              <1> 
  2866 000017F0 C3                  <1> 	retn
  2867                              <1> 
  2868                              <1> DR_POP_ERR:
  2869                              <1> 	; 24/12/2021
  2870 000017F1 59                  <1> 	pop	ecx			; CLEAR STACK
  2871                              <1> DR_ERR:
  2872 000017F2 800D[AC610000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2873 000017F9 EBEE                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2874                              <1> 
  2875                              <1> ;-------------------------------------------------------------------------------
  2876                              <1> ; FNC_ERR
  2877                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2878                              <1> ;	SET BAD COMMAND IN STATUS.
  2879                              <1> ;
  2880                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2881                              <1> ;-------------------------------------------------------------------------------
  2882                              <1> 
  2883                              <1> 	; 11/07/2022 - not needed (because diskio is used by kernel only)
  2884                              <1> 	
  2885                              <1> ;FNC_ERR:				; INVALID FUNCTION REQUEST
  2886                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2887                              <1> ;	; 24/12/2021
  2888                              <1> ;	mov	eax, esi		; RESTORE AL
  2889                              <1> ;	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2890                              <1> ;	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2891                              <1> ;	stc				; SET CARRY INDICATING ERROR
  2892                              <1> ;	retn
  2893                              <1> 
  2894                              <1> ;----------------------------------------------------------------
  2895                              <1> ; DR_TYPE_CHECK							:
  2896                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2897                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2898                              <1> ; ON ENTRY:							:
  2899                              <1> ;	AL = DRIVE TYPE						:
  2900                              <1> ; ON EXIT:							:
  2901                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2902                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2903                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2904                              <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 			:
  2905                              <1> ;----------------------------------------------------------------
  2906                              <1> DR_TYPE_CHECK:
  2907                              <1> 	; 12/07/2022
  2908                              <1> 	; 11/07/2022
  2909                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2910                              <1> 	; 24/12/2021
  2911                              <1> 	;push	eax ; 11/07/2022
  2912                              <1> 	;push	ecx ; 08/07/2022
  2913                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2914 000017FB BB[CC5B0000]        <1> 	mov	ebx, DR_TYPE
  2915                              <1> 	;;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2916                              <1> 	;mov	cl, DR_CNT
  2917 00001800 B406                <1> 	mov	ah, DR_CNT ; 11/07/2022
  2918                              <1> TYPE_CHK:	
  2919                              <1> 	;;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2920                              <1> 	;mov	ah, [ebx]
  2921                              <1> 	;cmp	al, ah			; DRIVE TYPE MATCH?
  2922 00001802 3A03                <1> 	cmp	al, [ebx] ; 11/07/2022
  2923 00001804 740E                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2924                              <1> 	; 16/02/2015 (32 bit address modification)
  2925 00001806 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2926                              <1> 	;loop	TYPE_CHK
  2927                              <1> 	;dec	cl
  2928 00001809 FECC                <1> 	dec	ah ; 11/07/2022
  2929 0000180B 75F5                <1> 	jnz	short TYPE_CHK
  2930                              <1> 	;
  2931 0000180D BB[2B5C0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2932                              <1> 					; Default for GET_PARM (11/12/2014)
  2933                              <1> 	;
  2934 00001812 F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2935                              <1> 	;jmp	short TYPE_RTN
  2936                              <1> 	; 12/07/2022
  2937 00001813 C3                  <1> 	retn
  2938                              <1> DR_TYPE_VALID:
  2939                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2940 00001814 43                  <1> 	inc	ebx
  2941 00001815 8B1B                <1> 	mov	ebx, [ebx]
  2942                              <1> TYPE_RTN:
  2943                              <1> 	;pop	ecx ; 08/07/2022
  2944                              <1> 	; 24/12/2021
  2945                              <1> 	;pop	eax ; 11/07/2022
  2946 00001817 C3                  <1> 	retn
  2947                              <1> 		
  2948                              <1> ;----------------------------------------------------------------
  2949                              <1> ; SEND_SPEC							:
  2950                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2951                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2952                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2953                              <1> ; ON EXIT:	NONE						:
  2954                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2955                              <1> ;----------------------------------------------------------------
  2956                              <1> SEND_SPEC:
  2957                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2958 00001818 50                  <1> 	push	eax			; SAVE EAX
  2959 00001819 B8[3F180000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2960 0000181E 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2961 0000181F B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2962 00001821 E8EC040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2963                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2964 00001826 28C0                <1> 	sub	al, al ; 08/07/2022
  2965 00001828 E8F4030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2966 0000182D E8E0040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2967                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2968 00001832 B001                <1> 	mov	al, 1 ; 08/07/2022
  2969 00001834 E8E8030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2970 00001839 E8D4040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2971 0000183E 58                  <1> 	pop	eax			; POP ERROR RETURN
  2972                              <1> SPECBAC:
  2973 0000183F 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2974 00001840 C3                  <1> 	retn
  2975                              <1> 
  2976                              <1> ;----------------------------------------------------------------
  2977                              <1> ; SEND_SPEC_MD							:
  2978                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2979                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (EBX)	:
  2980                              <1> ; ON ENTRY:	EBX = MEDIA/DRIVE PARAMETER TABLE		:
  2981                              <1> ; ON EXIT:	NONE						:
  2982                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022				:
  2983                              <1> ;----------------------------------------------------------------
  2984                              <1> SEND_SPEC_MD:
  2985                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2986                              <1> 	;push	eax ; 11/07/2022	; SAVE RATE DATA
  2987 00001841 B8[5E180000]        <1> 	mov	eax, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2988 00001846 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2989 00001847 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2990 00001849 E8C4040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2991 0000184E 8A23                <1>         mov	ah, [ebx+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2992 00001850 E8BD040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2993 00001855 8A6301              <1>         mov	ah, [ebx+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2994 00001858 E8B5040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2995 0000185D 58                  <1> 	pop	eax			; POP ERROR RETURN
  2996                              <1> SPEC_ESBAC:
  2997                              <1> 	;pop	eax ; 11/07/2022	; RESTORE ORIGINAL EAX VALUE
  2998 0000185E C3                  <1> 	retn
  2999                              <1> 
  3000                              <1> ;-------------------------------------------------------------------------------
  3001                              <1> ; XLAT_NEW  
  3002                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3003                              <1> ;	MODE TO NEW ARCHITECTURE.
  3004                              <1> ;
  3005                              <1> ; ON ENTRY:	EDI = DRIVE #
  3006                              <1> ;-------------------------------------------------------------------------------
  3007                              <1> XLAT_NEW:
  3008                              <1> 	; 11/07/2022
  3009                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3010                              <1> 	;cmp	edi, 1				; VALID DRIVE
  3011                              <1> 	;ja	short XN_OUT			; IF INVALID BACK
  3012                              <1> 	;
  3013 0000185F 80BF[B7610000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  3014 00001866 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3015                              <1> 	;
  3016                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  3017                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  3018                              <1> 	;or	cl, cl
  3019                              <1> 	;jz	short XN_0  ; 08/07/2022
  3020                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  3021                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  3022                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  3023                              <1> ;XN_0:	
  3024                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3025                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3026                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  3027                              <1> XN_OUT:
  3028 00001868 C3                  <1> 	retn
  3029                              <1> DO_DET:
  3030                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  3031                              <1> 	;;retn
  3032                              <1> 	;jmp	DRIVE_DET
  3033                              <1> 
  3034                              <1> ;-------------------------------------------------------------------------------
  3035                              <1> ; DRIVE_DET
  3036                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  3037                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  3038                              <1> ; ON ENTRY:	EDI = DRIVE #
  3039                              <1> ;-------------------------------------------------------------------------------
  3040                              <1> DRIVE_DET:
  3041                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3042 00001869 E8EE030000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  3043 0000186E E857050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  3044 00001873 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  3045 00001875 B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  3046 00001877 E8CF040000          <1> 	call	SEEK
  3047 0000187C 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  3048 0000187E B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  3049                              <1> SK_GIN:
  3050 00001880 FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  3051                              <1> 	;push	cx		
  3052                              <1> 	; 24/12/2021
  3053 00001882 51                  <1> 	push	ecx			; SAVE TRACK
  3054 00001883 E8C3040000          <1> 	call	SEEK
  3055 00001888 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  3056 0000188A B8[C4180000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  3057 0000188F 50                  <1> 	push	eax
  3058 00001890 B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  3059 00001892 E87B040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3060                              <1> 	; 08/07/2022
  3061 00001897 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  3062 00001899 88C4                <1> 	mov	ah, al			; AH = DRIVE
  3063 0000189B E872040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3064 000018A0 E8A6050000          <1> 	call	RESULTS			; GO GET STATUS
  3065 000018A5 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3066                              <1> 	;pop	cx			; RESTORE TRACK
  3067                              <1> 	; 24/12/2021
  3068 000018A6 59                  <1> 	pop	ecx
  3069 000018A7 F605[AD610000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  3070 000018AE 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  3071 000018B0 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  3072 000018B2 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  3073                              <1> 
  3074                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  3075                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  3076                              <1> 
  3077 000018B4 808F[B7610000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  3078 000018BB C3                  <1> 	retn				; ALL INFORMATION SET
  3079                              <1> IS_80:
  3080 000018BC 808F[B7610000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3081                              <1> DD_BAC:
  3082 000018C3 C3                  <1> 	retn
  3083                              <1> POP_BAC:
  3084                              <1> 	;pop	cx			; THROW AWAY
  3085                              <1> 	; 24/12/2021
  3086 000018C4 59                  <1> 	pop	ecx
  3087 000018C5 C3                  <1> 	retn
  3088                              <1> 
  3089                              <1> ;-------------------------------------------------------------------------------
  3090                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3091                              <1> ;-------------------------------------------------------------------------------
  3092                              <1> SETUP_STATE:
  3093                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3094 000018C6 F687[B7610000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3095 000018CD 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3096 000018CF 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3097 000018D3 F687[B7610000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3098 000018DA 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3099 000018DC F687[B7610000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3100 000018E3 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3101 000018E5 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3102                              <1> AX_SET:	
  3103 000018E9 80A7[B7610000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3104 000018F0 08A7[B7610000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3105 000018F6 8025[B4610000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3106 000018FD C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3107 00001900 0805[B4610000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3108                              <1> J1C:	
  3109 00001906 C3                  <1> 	retn
  3110                              <1> 
  3111                              <1> ;-------------------------------------------------------------------------------
  3112                              <1> ; MED_CHANGE	
  3113                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3114                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3115                              <1> ;
  3116                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3117                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3118                              <1> ;-------------------------------------------------------------------------------
  3119                              <1> MED_CHANGE:
  3120                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3121 00001907 E897050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3122 0000190C 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3123 0000190E 80A7[B7610000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3124                              <1> 
  3125                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3126                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3127                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3128                              <1> 
  3129 00001915 89F9                <1> 	mov	ecx, edi		; CL = DRIVE #
  3130 00001917 B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3131 00001919 D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3132 0000191B F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3133 0000191D FA                  <1> 	cli				; NO INTERRUPTS
  3134 0000191E 2005[AA610000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3135 00001924 FB                  <1> 	sti				; INTERRUPTS ENABLED
  3136 00001925 E832030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3137                              <1> 
  3138                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3139                              <1> 
  3140 0000192A E85BFEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3141 0000192F B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3142 00001931 E815040000          <1> 	call	SEEK			; ISSUE SEEK
  3143 00001936 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3144 00001938 E80E040000          <1> 	call	SEEK			; ISSUE SEEK
  3145 0000193D C605[AC610000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3146                              <1> OK1:
  3147 00001944 E85A050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3148 00001949 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3149                              <1> OK4:
  3150 0000194B C605[AC610000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3151                              <1> OK2:		
  3152 00001952 F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3153 00001953 C3                  <1> 	retn
  3154                              <1> MC_OUT:
  3155                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3156 00001954 C3                  <1> 	retn
  3157                              <1> 
  3158                              <1> ;-------------------------------------------------------------------------------
  3159                              <1> ; SEND_RATE
  3160                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3161                              <1> ; ON ENTRY:	EDI = DRIVE #
  3162                              <1> ; ON EXIT:	NONE
  3163                              <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022
  3164                              <1> ;-------------------------------------------------------------------------------
  3165                              <1> SEND_RATE:
  3166                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3167                              <1> 	;push	ax			; SAVE REG.
  3168                              <1> 	; 24/12/2021
  3169                              <1> 	;push	eax ; 11/07/2022
  3170 00001955 8025[B4610000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3171 0000195C 8A87[B7610000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3172 00001962 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3173 00001964 0805[B4610000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3174 0000196A C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3175 0000196D 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3176 00001971 EE                  <1> 	out	dx, al
  3177                              <1> 	;pop	ax			; RESTORE REG.
  3178                              <1> 	; 24/12/2021
  3179                              <1> 	;pop	eax ; 11/07/2022
  3180 00001972 C3                  <1> 	retn
  3181                              <1> 
  3182                              <1> ;-------------------------------------------------------------------------------
  3183                              <1> ; CHK_LASTRATE
  3184                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3185                              <1> ; ON ENTRY:
  3186                              <1> ;	EDI = DRIVE #
  3187                              <1> ; ON EXIT:
  3188                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3189                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3190                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022
  3191                              <1> ;-------------------------------------------------------------------------------
  3192                              <1> CHK_LASTRATE:
  3193                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3194                              <1> 	;push	ax			; SAVE REG.
  3195                              <1> 	; 24/12/2021
  3196                              <1> 	;push	eax ; 11/07/2022
  3197 00001973 8A25[B4610000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3198                              <1> 					; GET LAST DATA RATE SELECTED
  3199 00001979 8A87[B7610000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3200 0000197F 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3201 00001983 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3202                              <1> 					; ZF = 1 RATE IS THE SAME
  3203                              <1> 	;pop	ax			; RESTORE REG.
  3204                              <1> 	; 24/12/2021
  3205                              <1> 	;pop	eax ; 11/07/2022
  3206 00001985 C3                  <1> 	retn
  3207                              <1> 
  3208                              <1> ;-------------------------------------------------------------------------------
  3209                              <1> ; DMA_SETUP
  3210                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3211                              <1> ;
  3212                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3213                              <1> ;
  3214                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3215                              <1> ;-------------------------------------------------------------------------------
  3216                              <1> 
  3217                              <1> ; SI = Head #, # of Sectors or DASD Type
  3218                              <1> 
  3219                              <1> ; 22/08/2015
  3220                              <1> ; 08/02/2015 - Protected Mode Modification
  3221                              <1> ; 06/02/2015 - 07/02/2015
  3222                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3223                              <1> ; (DMA Addres = Physical Address)
  3224                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3225                              <1> ;
  3226                              <1> ; 04/02/2016 (clc)
  3227                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3228                              <1> ; 16/12/2014 (IODELAY)
  3229                              <1> 
  3230                              <1> DMA_SETUP:
  3231                              <1> 	; 18/07/2022
  3232                              <1> 	; 11/07/2022
  3233                              <1> 	;	ebp = buffer address
  3234                              <1> 	
  3235                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3236                              <1> 	;; 20/02/2015
  3237                              <1> 	;mov	edx, [ebp+4] ; 11/07/2022 ; Buffer address
  3238                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3239                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3240                              <1> 	;jnz	short dma_bnd_err_stc
  3241                              <1> 
  3242                              <1> 	; al = dma command
  3243                              <1> 	
  3244                              <1> ;	; 18/07/2022
  3245                              <1> ;	;	(512 bytes/sector only!) 
  3246                              <1> ;	; 24/12/2021
  3247                              <1> ;	push	eax			; DMA command
  3248                              <1> ;	;push	edx ; 11/07/2022	; *
  3249                              <1> ;	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3250                              <1> ;	mov	al, 3 ; 08/07/2022
  3251                              <1> ;	call	GET_PARM		; 
  3252                              <1> ;	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3253                              <1> ;	;mov	ax, si			; Sector count
  3254                              <1> ;	;mov	ah, al			; AH = # OF SECTORS
  3255                              <1> ;	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3256                              <1> ;	;shr	ax, 1			; AX = # SECTORS * 128
  3257                              <1> ;	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3258                              <1> ;	; 08/07/2022
  3259                              <1> ;	; 24/12/2021
  3260                              <1> ;	;mov	edx, esi
  3261                              <1> ;	sub	eax, eax
  3262                              <1> ;	;mov	ah, dl
  3263                              <1> ;	;shr	eax, 1
  3264                              <1> ;	mov	al, 128
  3265                              <1> ;	shl	eax, cl
  3266                              <1> ;	;
  3267                              <1> ;	dec	eax			; -1 FOR DMA VALUE
  3268                              <1> ;	mov	ecx, eax
  3269                              <1> ;	;pop	edx ; 11/07/2022	; *
  3270                              <1> ;	; 24/12/2021
  3271                              <1> ;	pop	eax
  3272                              <1> 
  3273                              <1> 	; 08/07/2022
  3274                              <1> 	;cmp	al, 42h
  3275                              <1>         ;jne	short NOT_VERF
  3276                              <1> 	;mov	edx, 0FF0000h
  3277                              <1> 	;jmp	short J33
  3278                              <1> ;NOT_VERF:
  3279                              <1> 	; 11/07/2022
  3280 00001986 89EA                <1> 	mov	edx, ebp
  3281                              <1> 	;
  3282                              <1> 	;add	dx, cx			; check for (64K) overflow
  3283                              <1> 	; 18/07/2022
  3284                              <1> 	; (512 bytes/sector)
  3285 00001988 6681C2FF01          <1> 	add	dx, 511 
  3286 0000198D 7239                <1> 	jc	short dma_bnd_err
  3287                              <1> 	;
  3288                              <1> 	;sub	dx, cx ; 11/07/2022	; Restore start address
  3289                              <1> J33:
  3290                              <1> 	; 08/07/2022
  3291 0000198F FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3292 00001990 E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LAST F/F
  3293                              <1> 	IODELAY				; WAIT FOR I/O
  2191 00001992 EB00                <2>  jmp short $+2
  2192 00001994 EB00                <2>  jmp short $+2
  3294 00001996 E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3295                              <1> 	;mov	eax, edx		; Buffer address
  3296                              <1> 	; 11/07/2022
  3297 00001998 89E8                <1> 	mov	eax, ebp ; buffer address
  3298 0000199A E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3299                              <1> 	IODELAY				; WAIT FOR I/O
  2191 0000199C EB00                <2>  jmp short $+2
  2192 0000199E EB00                <2>  jmp short $+2
  3300 000019A0 88E0                <1> 	mov	al, ah
  3301 000019A2 E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3302 000019A4 C1E810              <1> 	shr	eax, 16
  3303                              <1> 	IODELAY				; I/O WAIT STATE
  2191 000019A7 EB00                <2>  jmp short $+2
  2192 000019A9 EB00                <2>  jmp short $+2
  3304 000019AB E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3305                              <1> 	IODELAY
  2191 000019AD EB00                <2>  jmp short $+2
  2192 000019AF EB00                <2>  jmp short $+2
  3306                              <1> 	;;mov	ax, cx			; Byte count - 1
  3307                              <1> 	;mov	al, cl
  3308                              <1> 	; 18/07/2022
  3309                              <1> 	; (Byte count - 1 = 511)
  3310 000019B1 B0FF                <1> 	mov	al, 0FFh ; 511-256
  3311 000019B3 E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3312                              <1> 	IODELAY				; WAIT FOR I/O
  2191 000019B5 EB00                <2>  jmp short $+2
  2192 000019B7 EB00                <2>  jmp short $+2
  3313                              <1> 	;;mov	al, ah
  3314                              <1> 	;mov	al, ch
  3315                              <1> 	; 18/07/2022
  3316 000019B9 B001                <1> 	mov	al, 1 ; 256
  3317 000019BB E605                <1> 	out	DMA+5, al		; HIGH BYTE OF COUNT
  3318                              <1> 	IODELAY
  2191 000019BD EB00                <2>  jmp short $+2
  2192 000019BF EB00                <2>  jmp short $+2
  3319 000019C1 FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3320 000019C2 B002                <1> 	mov	al, 2			; MODE FOR 8237
  3321 000019C4 E60A                <1> 	out	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3322                              <1> 	
  3323 000019C6 F8                  <1> 	clc	; 04/02/2016
  3324                              <1> 	
  3325 000019C7 C3                  <1> 	retn
  3326                              <1> 
  3327                              <1> 	; 18/07/2022
  3328                              <1> ;dma_bnd_err_stc:
  3329                              <1> ;	stc
  3330                              <1> 
  3331                              <1> dma_bnd_err:
  3332 000019C8 C605[AC610000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3333 000019CF C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3334                              <1> 
  3335                              <1> ;-------------------------------------------------------------------------------
  3336                              <1> ; NEC_INIT	
  3337                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3338                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3339                              <1> ;
  3340                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3341                              <1> ;
  3342                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3343                              <1> ;-------------------------------------------------------------------------------
  3344                              <1> NEC_INIT:
  3345                              <1> 	; 11/07/2022
  3346                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3347                              <1> 	;push	ax			; SAVE NEC COMMAND
  3348                              <1> 	; 24/12/2021
  3349 000019D0 50                  <1> 	push	eax
  3350 000019D1 E886020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3351                              <1> 
  3352                              <1> ;-----	DO THE SEEK OPERATION
  3353                              <1> 
  3354                              <1> 	;mov	ch, [ebp+1]		; CH = TRACK #
  3355                              <1> 	; 11/07/2022
  3356 000019D6 89F1                <1> 	mov	ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector
  3357 000019D8 C1E908              <1> 	shr	ecx, 8
  3358                              <1> 	; ch = track #	
  3359                              <1> 
  3360 000019DB E86B030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3361                              <1> 	;pop	ax			; RECOVER COMMAND
  3362                              <1> 	; 24/12/2021
  3363 000019E0 58                  <1> 	pop	eax
  3364 000019E1 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3365 000019E3 BB[001A0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3366 000019E8 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3367                              <1> 
  3368                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3369                              <1> 
  3370 000019E9 E824030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3371 000019EE 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3372 000019F0 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3373 000019F2 C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3374 000019F5 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3375 000019F8 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3376 000019FA E813030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3377 000019FF 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3378                              <1> ER_1:
  3379 00001A00 C3                  <1> 	retn
  3380                              <1> 
  3381                              <1> ;-------------------------------------------------------------------------------
  3382                              <1> ; RWV_COM
  3383                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3384                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3385                              <1> ;
  3386                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3387                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3388                              <1> ;-------------------------------------------------------------------------------
  3389                              <1> RWV_COM:
  3390                              <1> 	; 11/07/2022
  3391                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3392 00001A01 B8[4E1A0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3393 00001A06 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3394                              <1> 	;mov	ah, [ebp+1]		; OUTPUT TRACK #
  3395                              <1> 	; 11/07/2022
  3396 00001A07 89F0                <1> 	mov	eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track
  3397 00001A09 C1E808              <1> 	shr	eax, 8
  3398                              <1> 	; ah = track # 
  3399 00001A0C E801030000          <1> 	call	NEC_OUTPUT
  3400 00001A11 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3401                              <1> 	; ah = head #
  3402 00001A13 E8FA020000          <1> 	call	NEC_OUTPUT
  3403                              <1>         ;mov	ah, [ebp]		; OUTPUT SECTOR #
  3404 00001A18 89F0                <1> 	mov	eax, esi
  3405 00001A1A 88C4                <1> 	mov	ah, al
  3406                              <1>  	; ah = sector #
  3407 00001A1C E8F1020000          <1> 	CALL	NEC_OUTPUT
  3408                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3409 00001A21 B003                <1> 	mov	al, 3 ; 08/07/2022
  3410 00001A23 E8F9010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3411 00001A28 E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3412                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3413 00001A2D B004                <1> 	mov	al, 4 ; 08/07/2022
  3414 00001A2F E8ED010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3415 00001A34 E8D9020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3416 00001A39 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3417                              <1> _R15:
  3418 00001A3C E8D1020000          <1> 	call	NEC_OUTPUT
  3419                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3420 00001A41 B006                <1> 	mov	al, 6 ; 08/07/2022
  3421 00001A43 E8D9010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3422 00001A48 E8C5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3423 00001A4D 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3424                              <1> ER_2:
  3425 00001A4E C3                  <1> 	retn
  3426                              <1> 
  3427                              <1> ;-------------------------------------------------------------------------------
  3428                              <1> ; NEC_TERM
  3429                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3430                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3431                              <1> ;
  3432                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3433                              <1> ;-------------------------------------------------------------------------------
  3434                              <1> 
  3435                              <1> NEC_TERM:
  3436                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3437                              <1> 
  3438                              <1> ;-----	LET THE OPERATION HAPPEN
  3439                              <1> 
  3440 00001A4F 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3441 00001A50 E8C7030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3442 00001A55 9C                  <1> 	pushfd	; 24/12/2021
  3443 00001A56 E8F0030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3444 00001A5B 724B                <1> 	jc	short SET_END_POP
  3445 00001A5D 9D                  <1> 	popfd	; 24/12/2021
  3446 00001A5E 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3447                              <1> 
  3448                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3449                              <1> 
  3450 00001A60 FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3451 00001A61 BE[AD610000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3452 00001A66 AC                  <1> 	lodsb				; GET ST0
  3453 00001A67 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3454 00001A69 7433                <1> 	jz	short SET_END
  3455 00001A6B 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3456 00001A6D 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3457                              <1> 
  3458                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3459                              <1> 
  3460 00001A6F AC                  <1> 	lodsb				; GET ST1
  3461 00001A70 D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3462 00001A72 B404                <1> 	mov	ah, RECORD_NOT_FND
  3463 00001A74 7222                <1> 	jc	short J19
  3464 00001A76 C0E002              <1> 	sal	al, 2
  3465 00001A79 B410                <1> 	mov	ah, BAD_CRC
  3466 00001A7B 721B                <1> 	jc	short J19
  3467 00001A7D D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3468 00001A7F B408                <1> 	mov	ah, BAD_DMA
  3469 00001A81 7215                <1> 	jc	short J19
  3470 00001A83 C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3471 00001A86 B404                <1> 	mov	ah, RECORD_NOT_FND
  3472 00001A88 720E                <1> 	jc	short J19
  3473 00001A8A D0E0                <1> 	sal	al, 1
  3474 00001A8C B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3475 00001A8E 7208                <1> 	jc	short J19
  3476 00001A90 D0E0                <1> 	sal	al, 1			; TEST MISSING ADDRESS MARK
  3477 00001A92 B402                <1> 	mov	ah, BAD_ADDR_MARK
  3478 00001A94 7202                <1> 	jc	short J19
  3479                              <1> 
  3480                              <1> ;----- 	NEC MUST HAVE FAILED
  3481                              <1> J18:
  3482 00001A96 B420                <1> 	mov	ah, BAD_NEC
  3483                              <1> J19:
  3484 00001A98 0825[AC610000]      <1> 	or	[DSKETTE_STATUS], ah
  3485                              <1> SET_END:
  3486 00001A9E 803D[AC610000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3487 00001AA5 F5                  <1> 	cmc
  3488 00001AA6 5E                  <1> 	pop	esi
  3489 00001AA7 C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3490                              <1> 
  3491                              <1> SET_END_POP:
  3492 00001AA8 9D                  <1> 	popfd	; 24/12/2021
  3493 00001AA9 EBF3                <1> 	jmp	short SET_END
  3494                              <1> 
  3495                              <1> ;-------------------------------------------------------------------------------
  3496                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3497                              <1> ;-------------------------------------------------------------------------------
  3498                              <1> DSTATE:
  3499                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3500 00001AAB 803D[AC610000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3501 00001AB2 753E                <1> 	jne	short SETBAC		; IF ERROR JUMP
  3502 00001AB4 808F[B7610000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3503 00001ABB F687[B7610000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3504 00001AC2 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3505 00001AC4 8A87[B7610000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3506 00001ACA 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3507 00001ACC 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3508 00001ACE 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3509                              <1> 
  3510                              <1> ;----- 	CHECK IF IT IS 1.44M
  3511                              <1> 
  3512 00001AD0 E843010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3513                              <1> 	;;20/02/2015
  3514                              <1> 	;;jc	short M_12		; CMOS BAD
  3515 00001AD5 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3516 00001AD7 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3517 00001AD9 7410                <1> 	je	short M_12		; YES
  3518                              <1> M_720:
  3519 00001ADB 80A7[B7610000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3520 00001AE2 808F[B7610000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3521 00001AE9 EB07                <1> 	jmp	short SETBAC		; BACK
  3522                              <1> M_12:	
  3523 00001AEB 808F[B7610000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3524                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3525                              <1> SETBAC:
  3526 00001AF2 C3                  <1> 	retn
  3527                              <1> 
  3528                              <1> ;-------------------------------------------------------------------------------
  3529                              <1> ; RETRY	
  3530                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3531                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3532                              <1> ;
  3533                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3534                              <1> ;-------------------------------------------------------------------------------
  3535                              <1> RETRY:
  3536                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3537 00001AF3 803D[AC610000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3538 00001AFA 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3539 00001AFC 803D[AC610000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3540 00001B03 743B                <1> 	je	short NO_RETRY
  3541 00001B05 8AA7[B7610000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3542 00001B0B F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3543 00001B0E 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3544 00001B10 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3545 00001B13 8A2D[B4610000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3546 00001B19 C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3547 00001B1C 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3548 00001B1F 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3549 00001B21 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3550                              <1> 
  3551                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3552                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3553                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3554                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3555                              <1> 
  3556 00001B23 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3557 00001B26 D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3558 00001B28 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3559 00001B2B 80A7[B7610000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3560                              <1> 					; RATE, DBL STEP OFF
  3561 00001B32 08A7[B7610000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3562 00001B38 C605[AC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3563 00001B3F F9                  <1> 	stc				; SET CARRY FOR RETRY
  3564                              <1> NO_RETRY:	; 08/07/2022
  3565 00001B40 C3                  <1> 	retn				; RETRY RETURN
  3566                              <1> 
  3567                              <1> ;NO_RETRY:
  3568                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3569                              <1> 	;RETn				; NO RETRY RETURN
  3570                              <1> 
  3571                              <1> ;-------------------------------------------------------------------------------
  3572                              <1> ; NUM_TRANS
  3573                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3574                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3575                              <1> ;
  3576                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3577                              <1> ;		SI-HI  = HEAD
  3578                              <1> ;		[BP]   = START SECTOR
  3579                              <1> ;
  3580                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3581                              <1> ;-------------------------------------------------------------------------------
  3582                              <1> NUM_TRANS:
  3583                              <1> 	; 11/07/2022
  3584                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3585 00001B41 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3586 00001B43 803D[AC610000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3587                              <1> 	; 24/12/2021
  3588 00001B4A 7529                <1> 	jne	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3589                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3590 00001B4C B004                <1> 	mov	al, 4 ; 08/07/2022
  3591 00001B4E E8CE000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3592                              <1> 	;mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3593 00001B53 A0[B2610000]        <1> 	mov	al, [NEC_STATUS+5]
  3594 00001B58 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3595 00001B5A 88CB                <1> 	mov	bl, cl ; 11/07/2022 ; sector #
  3596 00001B5C 3A2D[B1610000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3597 00001B62 750D                <1> 	jne	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3598                              <1> 	; 11/07/2022
  3599                              <1> 	;mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3600                              <1> 	;cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3601                              <1> 	;jz	short SAME_TR		; IF SAME TRACK NO INCREASE
  3602 00001B64 C1E908              <1> 	shr	ecx, 8 ; byte 3 = track # --> byte 2
  3603 00001B67 3A2D[B0610000]      <1> 	cmp	ch, [NEC_STATUS+3]
  3604 00001B6D 7404                <1> 	je	short SAME_TRK		
  3605                              <1> 	; 11/07/2022
  3606                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3607 00001B6F 00E0                <1> 	add	al, ah
  3608                              <1> DIF_HD:
  3609                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3610 00001B71 00E0                <1> 	add	al, ah
  3611                              <1> SAME_TRK:
  3612                              <1> 	;sub	bl, [ebp]		; SUBTRACT START FROM END
  3613                              <1> 	;mov	al, bl			; TO AL
  3614 00001B73 28D8                <1> 	sub	al, bl
  3615                              <1> NT_OUT:
  3616 00001B75 C3                  <1> 	retn
  3617                              <1> 
  3618                              <1> ;-------------------------------------------------------------------------------
  3619                              <1> ; SETUP_DBL
  3620                              <1> ;	CHECK DOUBLE STEP.
  3621                              <1> ;
  3622                              <1> ; ON ENTRY :	EDI = DRIVE #
  3623                              <1> ;
  3624                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3625                              <1> ;-------------------------------------------------------------------------------
  3626                              <1> SETUP_DBL:
  3627                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3628 00001B76 8AA7[B7610000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3629 00001B7C F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3630 00001B7F 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3631                              <1> 
  3632                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3633                              <1> 
  3634 00001B81 C605[A9610000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3635 00001B88 E8CF000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3636 00001B8D B500                <1> 	mov	ch, 0			; LOAD TRACK 0
  3637 00001B8F E8B7010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3638 00001B94 E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3639 00001B99 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3640                              <1> 
  3641                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3642                              <1> 
  3643 00001B9B 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3644 00001B9F F687[B7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3645 00001BA6 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3646 00001BA8 B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3647                              <1> 
  3648                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3649                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3650                              <1> ;	THEN SET DOUBLE STEP ON.
  3651                              <1> 
  3652                              <1> CNT_OK:
  3653 00001BAA C605[AB610000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3654                              <1> 	; 24/12/2021
  3655 00001BB1 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3656 00001BB2 C605[AC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3657 00001BB9 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3658 00001BBB D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3659 00001BBD C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3660                              <1> 	; 24/12/2021
  3661 00001BC0 50                  <1> 	push	eax			; SAVE HEAD
  3662 00001BC1 E885010000          <1> 	call	SEEK			; SEEK TO TRACK
  3663                              <1> 	; 24/12/2021
  3664 00001BC6 58                  <1> 	pop	eax			; RESTORE HEAD
  3665 00001BC7 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3666 00001BC9 E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3667 00001BCE 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3668 00001BCF 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3669 00001BD4 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3670                              <1> 	; 24/12/2021
  3671 00001BD5 59                  <1> 	pop	ecx			; RESTORE COUNT
  3672 00001BD6 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3673 00001BD8 FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3674 00001BDA 38CD                <1> 	cmp	ch, cl			; REACHED MAXIMUM YET
  3675 00001BDC 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3676                              <1> 
  3677                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3678                              <1> 
  3679                              <1> SD_ERR:	
  3680 00001BDE F9                  <1> 	stc				; SET CARRY FOR ERROR
  3681 00001BDF C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3682                              <1> 
  3683                              <1> DO_CHK:
  3684 00001BE0 8A0D[B0610000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3685 00001BE6 888F[B9610000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3686 00001BEC D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3687 00001BEE 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3688 00001BF0 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3689 00001BF2 808F[B7610000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3690                              <1> NO_DBL:
  3691 00001BF9 F8                  <1> 	clc				; CLEAR ERROR FLAG
  3692 00001BFA C3                  <1> 	retn
  3693                              <1> 
  3694                              <1> ;-------------------------------------------------------------------------------
  3695                              <1> ; READ_ID
  3696                              <1> ;	READ ID FUNCTION.
  3697                              <1> ;
  3698                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3699                              <1> ;
  3700                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3701                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3702                              <1> ;-------------------------------------------------------------------------------
  3703                              <1> READ_ID:
  3704                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3705 00001BFB B8[171C0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3706 00001C00 50                  <1> 	push	eax
  3707 00001C01 B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3708 00001C03 E80A010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3709 00001C08 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3710 00001C0A 88C4                <1> 	mov	ah, al
  3711 00001C0C E801010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3712 00001C11 E839FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3713 00001C16 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3714                              <1> ER_3:
  3715 00001C17 C3                  <1> 	retn
  3716                              <1> 
  3717                              <1> ;-------------------------------------------------------------------------------
  3718                              <1> ; CMOS_TYPE
  3719                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3720                              <1> ;
  3721                              <1> ; ON ENTRY:	EDI = DRIVE #
  3722                              <1> ;
  3723                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3724                              <1> ;-------------------------------------------------------------------------------
  3725                              <1> 
  3726                              <1> CMOS_TYPE: ; 11/12/2014
  3727                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3728 00001C18 8A87[4C5C0000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3729 00001C1E 20C0                <1> 	and 	al, al ; 18/12/2014
  3730 00001C20 C3                  <1> 	retn
  3731                              <1> 
  3732                              <1> ;-------------------------------------------------------------------------------
  3733                              <1> ; GET_PARM
  3734                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3735                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3736                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3737                              <1> ;	THE PARAMETER IN DL.
  3738                              <1> ;
  3739                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3740                              <1> ;
  3741                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3742                              <1> ;		AL DESTROYED
  3743                              <1> ;-------------------------------------------------------------------------------
  3744                              <1> GET_PARM:
  3745                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3746                              <1> 	;	 ENTRY:
  3747                              <1> 	;	     AL = INDEX
  3748                              <1> 	;	    EDI = DRIVE #
  3749                              <1> 	; 	 RETURN:
  3750                              <1> 	;	     AH = REQUESTED PARAMETER
  3751                              <1> 	;	     AL DESTROYED
  3752                              <1> 	
  3753                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3754                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3755                              <1> 	;push	esi ; 11/07/2022
  3756 00001C21 53                  <1> 	push	ebx			; SAVE EBX	
  3757 00001C22 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3758                              <1>    	; 17/12/2014
  3759                              <1> 	;mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3760                              <1> 	; 11/07/2022
  3761                              <1> 	;cmp	al, ah
  3762                              <1> 	;je	short gpndc
  3763                              <1> 
  3764                              <1> 	; 11/07/2022
  3765 00001C25 89F8                <1> 	mov	eax, edi
  3766 00001C27 3A05[415C0000]      <1> 	cmp	al, [pfd] ; is same with previous drive # ?
  3767 00001C2D 7423                <1> 	je	short gpndc	
  3768                              <1> 
  3769 00001C2F A2[415C0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3770                              <1> 
  3771 00001C34 53                  <1> 	push	ebx ; 08/02/2015
  3772                              <1> 	
  3773                              <1> 	;mov	bl, al 
  3774                              <1> 	; 11/12/2014
  3775                              <1> 	;mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3776                              <1> 	; 11/07/2022
  3777 00001C35 8A87[4C5C0000]      <1> 	mov	al, [edi+fd0_type]	; Drive type (0,1,2,3,4)	
  3778                              <1> 	; 18/12/2014
  3779 00001C3B 20C0                <1> 	and	al, al
  3780 00001C3D 7507                <1> 	jnz	short gpdtc
  3781 00001C3F BB[2B5C0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3782 00001C44 EB05                <1>         jmp     short gpdpu
  3783                              <1> gpdtc:	
  3784 00001C46 E8B0FBFFFF          <1> 	call	DR_TYPE_CHECK
  3785                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3786                              <1> gpdpu:
  3787 00001C4B 891D[C85B0000]      <1> 	mov	[DISK_POINTER], ebx
  3788 00001C51 5B                  <1> 	pop	ebx
  3789                              <1> gpndc:
  3790                              <1> 	;mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3791                              <1> 	;mov	ah, [esi+ebx]		; GET THE WORD
  3792                              <1> 	; 11/07/2022
  3793 00001C52 031D[C85B0000]      <1> 	add	ebx, [DISK_POINTER]
  3794 00001C58 8A23                <1> 	mov	ah, [ebx] 
  3795 00001C5A 5B                  <1> 	pop	ebx			; RESTORE EBX
  3796                              <1> 	;pop	esi ; 11/07/2022
  3797 00001C5B C3                  <1> 	retn
  3798                              <1> 
  3799                              <1> ;-------------------------------------------------------------------------------
  3800                              <1> ; MOTOR_ON
  3801                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3802                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3803                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3804                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3805                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3806                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3807                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3808                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3809                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3810                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3811                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3812                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3813                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3814                              <1> ;
  3815                              <1> ; ON ENTRY:	EDI = DRIVE #
  3816                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3817                              <1> ;-------------------------------------------------------------------------------
  3818                              <1> MOTOR_ON:
  3819                              <1> 	; 12/07/2022
  3820                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3821 00001C5C 53                  <1> 	push	ebx			; SAVE REG.
  3822 00001C5D E820000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3823 00001C62 721C                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3824                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3825                              <1> 	; 08/07/2022
  3826                              <1> 	;call	XLAT_NEW ; 12/07/2022	; TRANSLATE STATE TO PRESENT ARCH,
  3827                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3828                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3829                              <1> M_WAIT:
  3830                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3831 00001C64 B00A                <1> 	mov	al, 10 ; 08/07/2022
  3832 00001C66 E8B6FFFFFF          <1> 	call	GET_PARM
  3833                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3834 00001C6B 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3835                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3836 00001C6E 7302                <1> 	jae	short J13
  3837 00001C70 B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3838                              <1> 
  3839                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3840                              <1> GP2:	
  3841                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3842                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3843 00001C72 B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3844 00001C77 E817F7FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3845                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3846 00001C7C FECC                <1> 	dec	ah
  3847 00001C7E 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3848                              <1> MOT_IS_ON:
  3849 00001C80 5B                  <1> 	pop	ebx			; RESTORE REG.
  3850 00001C81 C3                  <1> 	retn
  3851                              <1> 
  3852                              <1> ;-------------------------------------------------------------------------------
  3853                              <1> ; TURN_ON
  3854                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3855                              <1> ;
  3856                              <1> ; ON ENTRY:	EDI = DRIVE #
  3857                              <1> ;
  3858                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3859                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3860                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3861                              <1> ;-------------------------------------------------------------------------------
  3862                              <1> TURN_ON:
  3863                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3864 00001C82 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3865 00001C84 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3866 00001C86 C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3867 00001C89 FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3868 00001C8A C605[AB610000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3869 00001C91 A0[AA610000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3870 00001C96 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3871 00001C98 B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3872 00001C9A D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3873                              <1> 
  3874                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3875                              <1> ;  BL = DRIVE SELECT DESIRED
  3876                              <1> ;  AH = MOTOR ON MASK DESIRED
  3877                              <1> 
  3878 00001C9C 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3879 00001C9E 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3880 00001CA0 8425[AA610000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3881 00001CA6 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3882                              <1> 
  3883                              <1> TURN_IT_ON:
  3884 00001CA8 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3885 00001CAA 8A3D[AA610000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3886 00001CB0 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3887 00001CB3 8025[AA610000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3888 00001CBA 0825[AA610000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3889 00001CC0 A0[AA610000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3890 00001CC5 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3891 00001CC7 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3892 00001CCA FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3893 00001CCB 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3894 00001CCD C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3895 00001CD0 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3896 00001CD2 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3897 00001CD6 EE                  <1> 	out	dx, al
  3898 00001CD7 38FB                <1> 	cmp	bl, bh			; NEW MOTOR TURNED ON ?
  3899                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3900 00001CD9 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3901 00001CDB F8                  <1> 	clc				; RESET CARRY MEANING WAIT
  3902 00001CDC C3                  <1> 	retn
  3903                              <1> 
  3904                              <1> NO_MOT_WAIT:
  3905 00001CDD FB                  <1> 	sti
  3906                              <1> no_mot_w1: ; 27/02/2015
  3907 00001CDE F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3908                              <1> 	;sti				; INTERRUPTS BACK ON
  3909 00001CDF C3                  <1> 	retn
  3910                              <1> 
  3911                              <1> ;-------------------------------------------------------------------------------
  3912                              <1> ; HD_WAIT
  3913                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3914                              <1> ;
  3915                              <1> ; ON ENTRY:	DI = DRIVE #
  3916                              <1> ;
  3917                              <1> ; ON EXIT:	EAX, EBX, ECX, EDX DESTROYED
  3918                              <1> ;-------------------------------------------------------------------------------
  3919                              <1> HD_WAIT:
  3920                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3921                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3922 00001CE0 B009                <1> 	mov	al, 9	; 08/07/2022
  3923 00001CE2 E83AFFFFFF          <1> 	CALL	GET_PARM
  3924 00001CE7 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3925 00001CE9 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3926 00001CEB F605[AA610000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3927                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3928                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3929                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3930 00001CF2 741D                <1> 	jz	short HW_DONE
  3931 00001CF4 B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3932 00001CF6 8A87[B7610000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3933 00001CFC 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3934 00001CFE 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3935 00001D00 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3936                              <1> ;GP3:
  3937 00001D02 B414                <1> 	mov	ah, HD320_SETTLE	; USE 320/360 HEAD SETTLE
  3938                              <1> ;	jmp	short DO_WAT
  3939                              <1> 
  3940                              <1> ;ISNT_WRITE:
  3941                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3942                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3943                              <1> 
  3944                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3945                              <1> DO_WAT:
  3946                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3947                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3948                              <1> J29:					; 	1 MILLISECOND LOOP
  3949                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3950                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3951                              <1> 	; 08/07/2022
  3952 00001D04 29C9                <1> 	sub	ecx, ecx
  3953 00001D06 B142                <1> 	mov	cl, 66
  3954 00001D08 E886F6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3955                              <1> 	;dec	al			; DECREMENT THE COUNT
  3956 00001D0D FECC                <1> 	dec	ah
  3957 00001D0F 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3958                              <1> HW_DONE:
  3959 00001D11 C3                  <1> 	retn
  3960                              <1> 
  3961                              <1> ;-------------------------------------------------------------------------------
  3962                              <1> ; NEC_OUTPUT
  3963                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3964                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3965                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3966                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3967                              <1> ; 
  3968                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3969                              <1> ;
  3970                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3971                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3972                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3973                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3974                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3975                              <1> ;
  3976                              <1> ;		EAX, ECX, EDX DESTROYED
  3977                              <1> ;-------------------------------------------------------------------------------
  3978                              <1> 
  3979                              <1> ; 09/12/2014 [Erdogan Tan] 
  3980                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3981                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3982                              <1> ;	This read only register facilitates the transfer of data between
  3983                              <1> ;	the system microprocessor and the controller.
  3984                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3985                              <1> ;	  with the system micrprocessor.
  3986                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3987                              <1> ;	  the transfer is to the controller.
  3988                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3989                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3990                              <1> ; Bit 3 - Reserved.
  3991                              <1> ; Bit 2 - Reserved.
  3992                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3993                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 0 is in the seek mode.
  3994                              <1> 
  3995                              <1> ; Data Register (3F5h)
  3996                              <1> ; This read/write register passes data, commands and parameters, and provides
  3997                              <1> ; diskette status information.
  3998                              <1>   		
  3999                              <1> NEC_OUTPUT:
  4000                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4001                              <1> 	;push	ebx			; SAVE REG.
  4002 00001D12 BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  4003                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  4004                              <1> 	; 16/12/2014
  4005                              <1> 	; waiting for (max.) 0.5 seconds
  4006                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4007                              <1> 	;
  4008                              <1> 	; 17/12/2014
  4009                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4010                              <1> 	;
  4011                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4012                              <1> 	;		go on.
  4013                              <1> 	;INPUT:
  4014                              <1> 	;	AH=Mask for isolation bits.
  4015                              <1> 	;	AL=pattern to look for.
  4016                              <1> 	;	DX=Port to test for
  4017                              <1> 	;	ECX=Number of memory refresh periods to delay.
  4018                              <1> 	;	     (normally 30 microseconds per period.)
  4019                              <1> 	;
  4020                              <1> 	;WFP_SHORT:  
  4021                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4022                              <1> 	;
  4023                              <1> 
  4024 00001D17 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4025                              <1> ;
  4026                              <1> ;WFPS_OUTER_LP:
  4027                              <1> ;	;
  4028                              <1> ;WFPS_CHECK_PORT:
  4029                              <1> J23:
  4030 00001D1C EC                  <1> 	in	al, dx			; GET STATUS
  4031 00001D1D 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  4032 00001D1F 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  4033 00001D21 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  4034                              <1> WFPS_HI:
  4035 00001D23 E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  4036 00001D25 A810                <1> 	test	al, 010h		; transition on memory
  4037 00001D27 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  4038                              <1> WFPS_LO:
  4039 00001D29 E461                <1> 	in	al, PORT_B		; SYS1
  4040 00001D2B A810                <1> 	test	al, 010h
  4041 00001D2D 74FA                <1> 	jz	short WFPS_LO
  4042                              <1> 	;loop	short WFPS_CHECK_PORT
  4043 00001D2F E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  4044                              <1> 
  4045                              <1> 	; fail
  4046                              <1> 
  4047                              <1> ;WFPS_TIMEOUT:
  4048                              <1> 
  4049                              <1> ;-----	FALL THRU TO ERROR RETURN
  4050                              <1> 
  4051 00001D31 800D[AC610000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4052                              <1> 	;pop	ebx			; RESTORE REG.
  4053 00001D38 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4054 00001D39 F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  4055 00001D3A C3                  <1> 	retn
  4056                              <1> 
  4057                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4058                              <1> 
  4059                              <1> J27:	
  4060 00001D3B 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  4061 00001D3D 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  4062 00001D3E EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  4063                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4064                              <1> 	; 27/02/2015
  4065 00001D3F 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  4066                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4067 00001D40 29C9                <1> 	sub	ecx, ecx
  4068 00001D42 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4069 00001D44 E84AF6FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  4070 00001D49 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  4071                              <1> 	;pop	ebx			; RESTORE REG
  4072 00001D4A C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  4073                              <1> 
  4074                              <1> ;-------------------------------------------------------------------------------
  4075                              <1> ; SEEK
  4076                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4077                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4078                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4079                              <1> ;
  4080                              <1> ; ON ENTRY:	EDI = DRIVE #
  4081                              <1> ;		CH = TRACK #
  4082                              <1> ;
  4083                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4084                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4085                              <1> ;-------------------------------------------------------------------------------
  4086                              <1> SEEK:
  4087                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4088 00001D4B 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4089 00001D4D B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4090 00001D4F 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  4091 00001D51 D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  4092 00001D53 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  4093 00001D55 8405[A9610000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4094 00001D5B 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4095                              <1> 
  4096 00001D5D 0805[A9610000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4097 00001D63 E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4098 00001D68 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  4099                              <1> 
  4100                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4101                              <1> 
  4102 00001D6A C605[AC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  4103 00001D71 E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4104 00001D76 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4105                              <1> 
  4106                              <1> AFT_RECAL:
  4107 00001D78 C687[B9610000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  4108 00001D7F 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  4109 00001D81 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4110                              <1> 
  4111                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4112                              <1> 
  4113 00001D83 F687[B7610000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4114 00001D8A 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4115 00001D8C D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  4116                              <1> 
  4117 00001D8E 3AAF[B9610000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  4118 00001D94 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  4119                              <1> 
  4120 00001D96 BA[C91D0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  4121 00001D9B 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4122 00001D9C 88AF[B9610000]      <1> 	mov	[DSK_TRK+edi], ch	; SAVE NEW CYLINDER AS PRESENT POSITION
  4123 00001DA2 B40F                <1> 	mov	ah, 0Fh			; SEEK COMMAND TO NEC
  4124 00001DA4 E869FFFFFF          <1> 	call	NEC_OUTPUT
  4125 00001DA9 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4126 00001DAB 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  4127 00001DAD E860FFFFFF          <1> 	call	NEC_OUTPUT
  4128 00001DB2 8AA7[B9610000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  4129 00001DB8 E855FFFFFF          <1> 	call	NEC_OUTPUT
  4130 00001DBD E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4131                              <1> 
  4132                              <1> ;-----	WAIT FOR HEAD SETTLE
  4133                              <1> 
  4134                              <1> DO_WAIT:
  4135 00001DC2 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  4136 00001DC3 E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4137 00001DC8 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  4138                              <1> RB:
  4139                              <1> NEC_ERR:
  4140                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4141                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4142 00001DC9 C3                  <1> 	retn				; RETURN TO CALLER
  4143                              <1> 
  4144                              <1> ;-------------------------------------------------------------------------------
  4145                              <1> ; RECAL
  4146                              <1> ;	RECALIBRATE DRIVE
  4147                              <1> ;
  4148                              <1> ; ON ENTRY:	EDI = DRIVE #
  4149                              <1> ;
  4150                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4151                              <1> ;-------------------------------------------------------------------------------
  4152                              <1> RECAL:
  4153                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4154                              <1> 	;push	cx
  4155                              <1> 	; 24/12/2021
  4156 00001DCA 51                  <1> 	push	ecx
  4157 00001DCB B8[E71D0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4158 00001DD0 50                  <1> 	push	eax
  4159 00001DD1 B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4160 00001DD3 E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4161 00001DD8 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4162 00001DDA 88DC                <1> 	mov	ah, bl
  4163 00001DDC E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4164 00001DE1 E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4165 00001DE6 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4166                              <1> RC_BACK:
  4167                              <1> 	;pop	cx
  4168                              <1> 	; 24/12/2021
  4169 00001DE7 59                  <1> 	pop	ecx
  4170 00001DE8 C3                  <1> 	RETn
  4171                              <1> 
  4172                              <1> ;-------------------------------------------------------------------------------
  4173                              <1> ; CHK_STAT_2
  4174                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4175                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4176                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4177                              <1> ;
  4178                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4179                              <1> ;-------------------------------------------------------------------------------
  4180                              <1> CHK_STAT_2:
  4181                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4182 00001DE9 B8[111E0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4183 00001DEE 50                  <1> 	push	eax
  4184 00001DEF E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4185 00001DF4 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4186 00001DF6 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4187 00001DF8 E815FFFFFF          <1> 	call	NEC_OUTPUT
  4188 00001DFD E849000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4189 00001E02 720C                <1> 	jc	short J34
  4190 00001E04 A0[AD610000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4191 00001E09 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4192 00001E0B 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4193 00001E0D 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4194 00001E0F F8                  <1> 	clc				; GOOD RETURN
  4195                              <1> J34:
  4196 00001E10 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4197                              <1> CS_BACK:
  4198 00001E11 C3                  <1> 	retn
  4199                              <1> J35:
  4200 00001E12 800D[AC610000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4201 00001E19 F9                  <1> 	stc				; ERROR RETURN CODE
  4202 00001E1A EBF4                <1> 	jmp	short J34
  4203                              <1> 
  4204                              <1> ;-------------------------------------------------------------------------------
  4205                              <1> ; WAIT_INT
  4206                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4207                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4208                              <1> ;	IF THE DRIVE IS NOT READY.
  4209                              <1> ;
  4210                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4211                              <1> ;-------------------------------------------------------------------------------
  4212                              <1> 
  4213                              <1> ; 17/12/2014
  4214                              <1> ; 2.5 seconds waiting !
  4215                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4216                              <1> ; amount of time to wait for completion interrupt from NEC.
  4217                              <1> 
  4218                              <1> WAIT_INT:
  4219                              <1> 	; 12/07/2022
  4220                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4221 00001E1C FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4222                              <1> 	; 12/07/2022
  4223                              <1> 	;clc				; CLEAR TIMEOUT INDICATOR
  4224                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4225                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4226                              <1> 
  4227                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4228                              <1> 	;
  4229                              <1> 	;WAIT_FOR_MEM:	
  4230                              <1> 	;	Waits for a bit at a specified memory location pointed
  4231                              <1> 	;	to by ES:[DI] to become set.
  4232                              <1> 	;INPUT:
  4233                              <1> 	;	AH=Mask to test with.
  4234                              <1> 	;	ES:[DI] = memory location to watch.
  4235                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4236                              <1> 	;	     (normally 30 microseconds per period.)
  4237                              <1> 
  4238                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4239                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4240                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4241                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4242                              <1> 	; 27/02/2015
  4243 00001E1D B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4244                              <1> WFMS_CHECK_MEM:
  4245 00001E22 F605[A9610000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4246 00001E29 7516                <1>         jnz     short J37
  4247                              <1> WFMS_HI:
  4248 00001E2B E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4249 00001E2D A810                <1> 	test	al, 010h		; transition on memory
  4250 00001E2F 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4251                              <1> WFMS_LO:
  4252 00001E31 E461                <1> 	in	al, PORT_B		; SYS1
  4253 00001E33 A810                <1> 	test	al, 010h
  4254 00001E35 74FA                <1> 	jz	short WFMS_LO
  4255 00001E37 E2E9                <1>         loop	WFMS_CHECK_MEM
  4256                              <1> ;WFMS_OUTER_LP:
  4257                              <1> ;;	or	bl, bl			; check outer counter
  4258                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4259                              <1> ;	dec	bl
  4260                              <1> ;	jz	short J36A	
  4261                              <1> ;	jmp	short WFMS_CHECK_MEM
  4262                              <1> 
  4263                              <1> 	;17/12/2014
  4264                              <1> 	;16/12/2014
  4265                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4266                              <1> ;J36:
  4267                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4268                              <1> ;	jnz	short J37
  4269                              <1> 	;16/12/2014
  4270                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4271                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4272                              <1> 	;jnz	short J36
  4273                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4274                              <1> ;	jb	short J36
  4275                              <1> 
  4276                              <1> ;WFMS_TIMEOUT:
  4277                              <1> ;J36A:
  4278 00001E39 800D[AC610000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4279 00001E40 F9                  <1> 	stc				; ERROR RETURN
  4280                              <1> J37:
  4281 00001E41 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4282 00001E42 8025[A9610000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4283 00001E49 9D                  <1> 	popf				; RECOVER CARRY
  4284 00001E4A C3                  <1> 	retn				; GOOD RETURN CODE
  4285                              <1> 
  4286                              <1> ;-------------------------------------------------------------------------------
  4287                              <1> ; RESULTS
  4288                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4289                              <1> ;	FOLLOWING AN INTERRUPT.
  4290                              <1> ;
  4291                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4292                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4293                              <1> ;-------------------------------------------------------------------------------
  4294                              <1> RESULTS:
  4295                              <1> 	; 12/07/2022
  4296                              <1> 	; 11/07/2022
  4297                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4298 00001E4B 57                  <1> 	push	edi
  4299 00001E4C BF[AD610000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4300 00001E51 B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4301 00001E53 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4302                              <1> 
  4303                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4304                              <1> 
  4305                              <1> _R10: 
  4306                              <1> 	; 16/12/2014
  4307                              <1> 	; wait for (max) 0.5 seconds
  4308                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4309                              <1> 	;xor	cx, cx			; COUNTER
  4310                              <1> 
  4311                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4312                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4313                              <1> 	; 27/02/2015
  4314                              <1> 
  4315 00001E57 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4316                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4317                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4318                              <1> 
  4319                              <1> WFPSR_OUTER_LP:
  4320                              <1> 	;
  4321                              <1> WFPSR_CHECK_PORT:
  4322                              <1> J39:					; WAIT FOR MASTER
  4323 00001E5C EC                  <1> 	in	al, dx			; GET STATUS
  4324 00001E5D 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4325 00001E5F 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4326 00001E61 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4327                              <1> WFPSR_HI:
  4328 00001E63 E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4329 00001E65 A810                <1> 	test	al, 010h		; transition on memory
  4330 00001E67 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4331                              <1> WFPSR_LO:
  4332 00001E69 E461                <1> 	in	al, PORT_B		; SYS1
  4333 00001E6B A810                <1> 	test	al, 010h
  4334 00001E6D 74FA                <1> 	jz	short WFPSR_LO
  4335 00001E6F E2EB                <1>         loop	WFPSR_CHECK_PORT
  4336                              <1> 	
  4337                              <1> 	;; 27/02/2015
  4338                              <1> 	;;dec	bh
  4339                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4340                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4341                              <1> 
  4342                              <1> 	;;mov	byte [wait_count], 0
  4343                              <1> ;J39:					; WAIT FOR MASTER
  4344                              <1> ;	in	al, dx			; GET STATUS
  4345                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4346                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4347                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4348                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4349                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4350                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4351                              <1> 	;
  4352                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4353                              <1> 	;;jb	short J39	
  4354                              <1> 
  4355                              <1> ;WFPSR_TIMEOUT:
  4356 00001E71 800D[AC610000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4357 00001E78 F9                  <1> 	stc				; SET ERROR RETURN
  4358 00001E79 EB26                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4359                              <1> 
  4360                              <1> ;-----	READ IN THE STATUS
  4361                              <1> 
  4362                              <1> J42:
  4363 00001E7B EB00                <1> 	JMP	$+2			; I/O DELAY
  4364                              <1> 	;inc	dx			; POINT AT DATA PORT
  4365 00001E7D FEC2                <1> 	inc	dl
  4366 00001E7F EC                  <1> 	in	al, dx			; GET THE DATA
  4367                              <1> 	; 16/12/2014
  4368                              <1> 	NEWIODELAY
  2196 00001E80 E6EB                <2>  out 0EBh,al
  4369                              <1> 	
  4370                              <1> 	;mov	[edi], al		; STORE THE BYTE
  4371                              <1> 	;inc	edi			; INCREMENT THE POINTER
  4372                              <1> 	; 11/07/2022
  4373 00001E82 AA                  <1> 	stosb
  4374                              <1> 
  4375                              <1> 	; 16/12/2014
  4376                              <1> ;	push	cx
  4377                              <1> ;	mov	cx, 30
  4378                              <1> ;wdw2:
  4379                              <1> ;	NEWIODELAY
  4380                              <1> ;	loop	wdw2
  4381                              <1> ;	pop	cx
  4382                              <1> 
  4383                              <1> 	;mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4384                              <1> 	; 12/07/2022
  4385 00001E83 29C9                <1> 	sub	ecx, ecx
  4386 00001E85 B103                <1> 	mov	cl, 3
  4387 00001E87 E807F5FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4388                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4389 00001E8C FECA                <1> 	dec	dl
  4390 00001E8E EC                  <1> 	in	al, dx			; GET STATUS
  4391                              <1> 	; 16/12/2014
  4392                              <1> 	NEWIODELAY
  2196 00001E8F E6EB                <2>  out 0EBh,al
  4393                              <1> 	;
  4394 00001E91 A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4395 00001E93 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4396                              <1> 
  4397 00001E95 FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4398 00001E97 75BE                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4399 00001E99 800D[AC610000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4400 00001EA0 F9                  <1> 	stc				; SET ERROR FLAG
  4401                              <1> 
  4402                              <1> ;-----	RESULT OPERATION IS DONE
  4403                              <1> POPRES:
  4404 00001EA1 5F                  <1> 	pop	edi
  4405 00001EA2 C3                  <1> 	retn				; RETURN WITH CARRY SET
  4406                              <1> 
  4407                              <1> ;-------------------------------------------------------------------------------
  4408                              <1> ; READ_DSKCHNG
  4409                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4410                              <1> ;
  4411                              <1> ; ON ENTRY:	EDI = DRIVE #
  4412                              <1> ;
  4413                              <1> ; ON EXIT:	EDI = DRIVE #
  4414                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4415                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4416                              <1> ;		EAX, ECX, EDX DESTROYED
  4417                              <1> ;-------------------------------------------------------------------------------
  4418                              <1> READ_DSKCHNG:
  4419                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4420 00001EA3 E8B4FDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4421 00001EA8 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4422 00001EAC EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4423 00001EAD A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4424 00001EAF C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4425                              <1> 
  4426                              <1> fdc_int:  
  4427                              <1> 	  ; 30/07/2015	
  4428                              <1> 	  ; 16/02/2015
  4429                              <1> ;int_0Eh: ; 11/12/2014
  4430                              <1> 
  4431                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  4432                              <1> ; DISK_INT
  4433                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4434                              <1> ;
  4435                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4436                              <1> ;-------------------------------------------------------------------------------
  4437                              <1> DISK_INT_1:
  4438                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4439                              <1> 	;push	eax			; SAVE WORK REGISTER
  4440                              <1> 	; 24/12/2021
  4441 00001EB0 50                  <1> 	push	eax
  4442 00001EB1 1E                  <1> 	push	ds
  4443 00001EB2 66B81000            <1> 	mov	ax, KDATA
  4444 00001EB6 8ED8                <1> 	mov 	ds, ax
  4445 00001EB8 800D[A9610000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4446 00001EBF B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4447 00001EC1 E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4448 00001EC3 1F                  <1> 	pop	ds
  4449                              <1> 	;pop	ax			; RECOVER REGISTER
  4450                              <1> 	; 24/12/2021
  4451 00001EC4 58                  <1> 	pop	eax
  4452 00001EC5 CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4453                              <1> 
  4454                              <1> ;-------------------------------------------------------------------------------
  4455                              <1> ; DSKETTE_SETUP
  4456                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4457                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4458                              <1> ;-------------------------------------------------------------------------------
  4459                              <1> DSKETTE_SETUP:
  4460                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4461                              <1> 	;push	eax			; SAVE REGISTERS
  4462                              <1> 	;push	ebx
  4463                              <1> 	;push	ecx
  4464 00001EC6 52                  <1> 	push	edx
  4465                              <1> 	;push	edi
  4466                              <1> 	; 14/12/2014
  4467                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4468                              <1> 	;
  4469                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4470                              <1> 
  4471 00001EC7 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4472 00001EC9 29C9                <1> 	sub	ecx, ecx
  4473 00001ECB 66890D[B7610000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4474                              <1> 	; 08/07/2022
  4475                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4476 00001ED2 800D[B4610000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4477 00001ED9 880D[A9610000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4478 00001EDF 880D[AB610000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4479 00001EE5 880D[AA610000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4480 00001EEB 880D[AC610000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4481                              <1> 	;
  4482                              <1> 	; 28/02/2015
  4483                              <1> 	;mov	word [cfd], 100h 
  4484 00001EF1 E894F8FFFF          <1> 	call	DSK_RESET
  4485 00001EF6 5A                  <1> 	pop	edx
  4486 00001EF7 C3                  <1> 	retn
  4487                              <1> 
  4488                              <1> ;//////////////////////////////////////////////////////
  4489                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4490                              <1> ;
  4491                              <1> 
  4492                              <1> ; 12/07/2022
  4493                              <1> ;int13h: ; 21/02/2015
  4494                              <1> ;	pushfd
  4495                              <1> ;	push 	cs
  4496                              <1> ;	call 	DISK_IO
  4497                              <1> ;	retn
  4498                              <1> 
  4499                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4500                              <1> ;/////////////////////////////////////////////////////////////////////
  4501                              <1> 
  4502                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4503                              <1> ; ((Direct call instead of int 13h simulation))
  4504                              <1> ;
  4505                              <1> ;		Function in AL
  4506                              <1> ;			0 = reset
  4507                              <1> ;			1 = read
  4508                              <1> ;			2 = write
  4509                              <1> ;		Disk drive number in DL
  4510                              <1> ;			0 & 1 = floppy disks	
  4511                              <1> ;			80h .. 83h = hard disks
  4512                              <1> ;		Sector address (LBA) in ECX
  4513                              <1> ;		Buffer address in EBX
  4514                              <1> ;		R/W sector count is (always) 1
  4515                              <1> ;
  4516                              <1> ;		Return:
  4517                              <1> ;			Status in AH (>0 = error code)
  4518                              <1> ;			if CF = 1 -> error code in AH
  4519                              <1> ;			if CF = 0 -> successful
  4520                              <1> ;			AL = undefined
  4521                              <1> ;
  4522                              <1> ;		Modified registers: (only) EAX
  4523                              <1> 
  4524                              <1> ; 10/07/2022
  4525                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4526                              <1> 
  4527                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4528                              <1> ; 23/02/2015
  4529                              <1> ; 21/02/2015 (unix386.s)
  4530                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4531                              <1> ;
  4532                              <1> ; Original Source Code:
  4533                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4534                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4535                              <1> ;
  4536                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4537                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4538                              <1> ;
  4539                              <1> 
  4540                              <1> ;The wait for controller to be not busy is 10 seconds.
  4541                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4542                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4543                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4544                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4545                              <1> 
  4546                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4547                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4548                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4549                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4550                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4551                              <1> 
  4552                              <1> ;The wait for Data request on read and write longs is
  4553                              <1> ;2000 us. (?)
  4554                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4555                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4556                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4557                              <1> 
  4558                              <1> ; Port 61h (PORT_B)
  4559                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4560                              <1> 
  4561                              <1> ; 23/12/2014
  4562                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4563                              <1> 
  4564                              <1> 	; 11/07/2022
  4565                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4566                              <1> 
  4567                              <1> ;--- INT 13H -------------------------------------------------------------------
  4568                              <1> ;									       :
  4569                              <1> ; FIXED DISK I/O INTERFACE						       :
  4570                              <1> ;									       :
  4571                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4572                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4573                              <1> ;									       :
  4574                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4575                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4576                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4577                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4578                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4579                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4580                              <1> ;									       :
  4581                              <1> ;------------------------------------------------------------------------------:
  4582                              <1> ;									       :
  4583                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4584                              <1> ;									       :
  4585                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4586                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY                        :
  4587                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY                       :
  4588                              <1> ;									       :
  4589                              <1> ;------------------------------------------------------------------------------:
  4590                              <1> ;									       :
  4591                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4592                              <1> ;									       :
  4593                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4594                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4595                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4596                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4597                              <1> ;									       :
  4598                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4599                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4600                              <1> ;				 (10 BITS TOTAL)			       :
  4601                              <1> ;									       :
  4602                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4603                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4604                              <1> ;									       :
  4605                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4606                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4607                              <1> ;									       :
  4608                              <1> ;------------------------------------------------------------------------------:
  4609                              <1> ; OUTPUT								       :
  4610                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4611                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4612                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4613                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4614                              <1> ;									       :
  4615                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4616                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4617                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4618                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4619                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4620                              <1> ;		REWRITTEN.						       :
  4621                              <1> ;									       :
  4622                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4623                              <1> ;	   INPUT:							       :
  4624                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4625                              <1> ;	   OUTPUT:							       :
  4626                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4627                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4628                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4629                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4630                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4631                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4632                              <1> ;									       :
  4633                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4634                              <1> ;	INFORMATION.							       :
  4635                              <1> ;									       :
  4636                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4637                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4638                              <1> ;									       :
  4639                              <1> ;-------------------------------------------------------------------------------
  4640                              <1> 
  4641                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4642                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4643                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4644                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4645                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4646                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4647                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4648                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4649                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4650                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4651                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4652                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4653                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4654                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4655                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4656                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4657                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4658                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4659                              <1> 
  4660                              <1> ;--------------------------------------------------------
  4661                              <1> ;							:
  4662                              <1> ; FIXED DISK PARAMETER TABLE				:
  4663                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4664                              <1> ;							:
  4665                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4666                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4667                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4668                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4669                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4670                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4671                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4672                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4673                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4674                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4675                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4676                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4677                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4678                              <1> ;							:
  4679                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4680                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4681                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4682                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4683                              <1> ;							:
  4684                              <1> ;--------------------------------------------------------
  4685                              <1> 
  4686                              <1> ;--------------------------------------------------------
  4687                              <1> ;							:
  4688                              <1> ; HARDWARE SPECIFIC VALUES				:
  4689                              <1> ;							:
  4690                              <1> ;  -  CONTROLLER I/O PORT				:
  4691                              <1> ;							:
  4692                              <1> ;     > WHEN READ FROM: 				:
  4693                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4694                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4695                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4696                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4697                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4698                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4699                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4700                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4701                              <1> ;							:
  4702                              <1> ;     > WHEN WRITTEN TO:				:
  4703                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4704                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4705                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4706                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4707                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4708                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4709                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4710                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4711                              <1> ;							:
  4712                              <1> ;--------------------------------------------------------
  4713                              <1> 
  4714                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4715                              <1> ;HF1_PORT	equ	0170h	
  4716                              <1> ;HF_REG_PORT	EQU	03F6H
  4717                              <1> ;HF1_REG_PORT	equ	0376h
  4718                              <1> 
  4719                              <1> HDC1_BASEPORT	equ	1F0h
  4720                              <1> HDC2_BASEPORT	equ	170h		
  4721                              <1> 
  4722                              <1> align 2
  4723                              <1> 
  4724                              <1> ;-----		STATUS REGISTER
  4725                              <1> 
  4726                              <1> ST_ERROR	EQU	00000001B	;
  4727                              <1> ST_INDEX	EQU	00000010B	;
  4728                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4729                              <1> ST_DRQ		EQU	00001000B	;
  4730                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4731                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4732                              <1> ST_READY	EQU	01000000B	;
  4733                              <1> ST_BUSY 	EQU	10000000B	;
  4734                              <1> 
  4735                              <1> ;-----		ERROR REGISTER
  4736                              <1> 
  4737                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4738                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4739                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4740                              <1> ;		EQU	00001000B	; NOT USED
  4741                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4742                              <1> ;		EQU	00100000B	; NOT USED
  4743                              <1> ERR_DATA_ECC	EQU	01000000B
  4744                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4745                              <1> 
  4746                              <1> 
  4747                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4748                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4749                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4750                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4751                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4752                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4753                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4754                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4755                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4756                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4757                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4758                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4759                              <1> 
  4760                              <1> ;MAX_FILE	EQU	2
  4761                              <1> ;S_MAX_FILE	EQU	2
  4762                              <1> MAX_FILE	equ	4		; 22/12/2014
  4763                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4764                              <1> 
  4765                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4766                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4767                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4768                              <1> 
  4769                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4770                              <1> 
  4771                              <1> ;-----		COMMAND BLOCK REFERENCE
  4772                              <1> 
  4773                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4774                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4775                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4776                              <1> ; 19/12/2014
  4777                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4778                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4779                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4780                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4781                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4782                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4783                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4784                              <1> 
  4785                              <1> align 2
  4786                              <1> 
  4787                              <1> ;----------------------------------------------------------------
  4788                              <1> ; FIXED DISK I/O SETUP						:
  4789                              <1> ;								:
  4790                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4791                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4792                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4793                              <1> ;								:
  4794                              <1> ;----------------------------------------------------------------
  4795                              <1> 
  4796                              <1> 	; 12/07/2022
  4797                              <1> 	; 11/07/2022
  4798                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4799                              <1> 
  4800                              <1> DISK_SETUP:
  4801                              <1> 	;cli
  4802                              <1> 	;;mov	ax, ABS0 			; GET ABSOLUTE SEGMENT
  4803                              <1> 	;xor	ax, ax
  4804                              <1> 	;mov	ds, ax				; SET SEGMENT REGISTER
  4805                              <1> 	;mov	ax, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4806                              <1> 	;mov	[DISK_VECTOR], ax		; INTO INT 40H
  4807                              <1> 	;mov	ax, [ORG_VECTOR+2]
  4808                              <1> 	;mov	[DISK_VECTOR+2], ax
  4809                              <1> 	;mov	word [ORG_VECTOR], DISK_IO	; FIXED DISK HANDLER
  4810                              <1> 	;mov	[ORG_VECTOR+2], cs
  4811                              <1> 	; 1st controller (primary master, slave) - IRQ 14
  4812                              <1> 	;;mov	word [HDISK_INT], HD_INT	; FIXED DISK INTERRUPT
  4813                              <1> 	;mov	word [HDISK_INT1], HD_INT	;
  4814                              <1> 	;;mov	[HDISK_INT+2], cs
  4815                              <1> 	;mov	[HDISK_INT1+2], cs
  4816                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4817                              <1> 	;mov	word [HDISK_INT2], HD1_INT	;
  4818                              <1> 	;mov	[HDISK_INT2+2], cs
  4819                              <1> 	;
  4820                              <1> 	;;mov	word [HF_TBL_VEC], HD0_DPT	; PARM TABLE DRIVE 80
  4821                              <1> 	;;mov	word [HF_TBL_VEC+2], DPT_SEGM
  4822                              <1> 	;;mov	word [HF1_TBL_VEC], HD1_DPT	; PARM TABLE DRIVE 81
  4823                              <1> 	;;mov	word [HF1_TBL_VEC+2], DPT_SEGM
  4824                              <1> 	;push	cs
  4825                              <1> 	;pop	ds
  4826                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4827                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4828 00001EF8 C705[C0610000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4828 00001F00 0900                <1>
  4829                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4830                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4831 00001F02 C705[C4610000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4831 00001F0A 0900                <1>
  4832                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4833                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4834 00001F0C C705[C8610000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4834 00001F14 0900                <1>
  4835                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4836                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4837 00001F16 C705[CC610000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4837 00001F1E 0900                <1>
  4838                              <1> 	;
  4839                              <1> 	;;in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  4840                              <1> 	;;;and	al, 0BFh
  4841                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4842                              <1> 	;;;JMP	$+2
  4843                              <1> 	;;IODELAY
  4844                              <1> 	;;out	INTB01, al
  4845                              <1> 	;;IODELAY
  4846                              <1> 	;;in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  4847                              <1> 	;;and	al, 0FBh 		; SECOND CHIP
  4848                              <1> 	;;;JMP	$+2
  4849                              <1> 	;;IODELAY
  4850                              <1> 	;;out	INTA01, al
  4851                              <1> 	;
  4852                              <1> 	;sti
  4853                              <1> 	;;push	ds			; MOVE ABS0 POINTER TO
  4854                              <1> 	;;pop	es			; EXTRA SEGMENT POINTER
  4855                              <1> 	;;;call	DDS			; ESTABLISH DATA SEGMENT
  4856                              <1> 	;;mov	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4857                              <1> 	;;mov	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4858                              <1> 	;;mov	byte [CONTROL_BYTE],0
  4859                              <1> 	;;mov	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4860                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4861                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4862                              <1> 	;mov	si, hd0_type
  4863 00001F20 BE[4E5C0000]        <1> 	mov	esi, hd0_type
  4864                              <1> 	;;mov	cx, 4
  4865                              <1> 	;mov	ecx, 4
  4866                              <1> 	; 11/07/2022
  4867 00001F25 29C9                <1> 	sub	ecx, ecx
  4868 00001F27 B104                <1> 	mov	cl, 4
  4869                              <1> hde_l:
  4870 00001F29 AC                  <1> 	lodsb
  4871 00001F2A 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4872 00001F2C 7206                <1> 	jb	short _L4
  4873 00001F2E FE05[BC610000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4874                              <1> _L4: ; 26/02/2015
  4875 00001F34 E2F3                <1> 	loop	hde_l	
  4876                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4877                              <1> ;L4:
  4878                              <1> 	; 
  4879                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4880                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4881                              <1> 	;;mov 	cl, 3
  4882                              <1> 	;;
  4883                              <1> 	;;mov	dl, 80h			; CHECK THE CONTROLLER
  4884                              <1> ;;hdc_dl:
  4885                              <1> 	;;mov	ah, 14h			; USE CONTROLLER DIAGNOSTIC COMMAND
  4886                              <1> 	;;int	13h			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4887                              <1> 	;;;jc	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4888                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4889                              <1> 	;;jnc	short hdc_reset0
  4890                              <1> 	;;loop	hdc_dl
  4891                              <1> 	;;; 27/12/2014
  4892                              <1> 	;;stc
  4893                              <1> 	;;retn
  4894                              <1> 	;
  4895                              <1> ;;hdc_reset0:
  4896                              <1> 	; 18/01/2015
  4897 00001F36 8A0D[BC610000]      <1> 	mov	cl, [HF_NUM]
  4898 00001F3C 20C9                <1> 	and	cl, cl
  4899 00001F3E 740D                <1> 	jz	short POD_DONE
  4900                              <1> 	;
  4901 00001F40 B27F                <1> 	mov	dl, 7Fh
  4902                              <1> hdc_reset1:
  4903 00001F42 FEC2                <1> 	inc	dl
  4904                              <1> 	;; 31/12/2015
  4905                              <1> 	;;push	dx
  4906                              <1> 	;;push	cx
  4907                              <1> 	;;push	ds
  4908                              <1> 	;;sub	ax, ax
  4909                              <1> 	;;mov	ds, ax
  4910                              <1> 	;;mov	ax, [TIMER_LOW]		; GET START TIMER COUNTS
  4911                              <1> 	;;pop	ds
  4912                              <1> 	;;mov	bx, ax
  4913                              <1> 	;;add	ax, 6*182		; 60 SECONDS* 18.2
  4914                              <1> 	;;mov	cx, ax
  4915                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4916                              <1> 	;;
  4917                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4918                              <1> 	;;call	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4919                              <1> 	;;pop	cx
  4920                              <1> 	;;pop	dx
  4921                              <1> 	;;
  4922                              <1> 	; 18/01/2015
  4923                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4924                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4925                              <1> 	;mov	ah, 5 ; ALTERNATE RESET
  4926                              <1> 	;;int	13h
  4927                              <1> 	;call	int13h
  4928                              <1> 	; 12/07/2022
  4929 00001F44 30C0                <1> 	xor	al, al  ; reset
  4930 00001F46 E803000000          <1> 	call	DISK_IO	
  4931                              <1> 	;
  4932 00001F4B E2F5                <1> 	loop	hdc_reset1
  4933                              <1> POD_DONE:
  4934 00001F4D C3                  <1> 	retn
  4935                              <1> 
  4936                              <1> ;----------------------------------------
  4937                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4938                              <1> ;----------------------------------------
  4939                              <1> 
  4940                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4941                              <1> ; ((Direct call instead of int 13h simulation))
  4942                              <1> ;
  4943                              <1> ;		Function in AL
  4944                              <1> ;			0 = reset
  4945                              <1> ;			1 = read
  4946                              <1> ;			2 = write
  4947                              <1> ;		Disk drive number in DL
  4948                              <1> ;			0 & 1 = floppy disks	
  4949                              <1> ;			80h .. 83h = hard disks
  4950                              <1> ;		Sector address (LBA) in ECX
  4951                              <1> ;		Buffer address in EBX
  4952                              <1> ;		R/W sector count is (always) 1
  4953                              <1> ;
  4954                              <1> ;		Return:
  4955                              <1> ;			Status in AH (>0 = error code)
  4956                              <1> ;			if CF = 1 -> error code in AH
  4957                              <1> ;			if CF = 0 -> successful
  4958                              <1> ;			AL = undefined
  4959                              <1> ;
  4960                              <1> ;		Modified registers: (only) EAX
  4961                              <1> 	
  4962                              <1> 
  4963                              <1> ; 11/07/2022
  4964                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4965                              <1> 
  4966                              <1> DISK_IO:
  4967                              <1> 	; 11/07/2022
  4968                              <1> 	; save registers
  4969 00001F4E 57                  <1> 	push	edi			; ANY
  4970 00001F4F 56                  <1> 	push	esi			; ANY
  4971 00001F50 53                  <1> 	push	ebx			; BUFFER ADDRESS
  4972 00001F51 51                  <1> 	push	ecx			; SECTOR ADDRESS (LBA)
  4973 00001F52 52                  <1> 	push	edx			; DRIVE NUMBER (DL)
  4974                              <1> 
  4975                              <1> 	;cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4976                              <1> 	;;jae	short A1		; YES, HANDLE HERE
  4977                              <1> 	;;;;int	40H			; DISKETTE HANDLER
  4978                              <1> 	;;;call	int40h
  4979                              <1> 	;;jb	DISKETTE_IO_1
  4980                              <1> 	;; 24/12/2021
  4981                              <1> 	;jnb	short A1
  4982                              <1> 	;jmp	DISKETTE_IO_1
  4983                              <1> 
  4984                              <1> 	; 11/07/2022
  4985 00001F53 80FA80              <1> 	cmp	dl, 80h
  4986 00001F56 730B                <1> 	jae	short A1
  4987                              <1> 
  4988 00001F58 E8CAF6FFFF          <1> 	call	DISKETTE_IO_1
  4989                              <1> 
  4990                              <1> DISK_IO_RTN:
  4991                              <1> 	; restore registers
  4992 00001F5D 5A                  <1> 	pop	edx
  4993 00001F5E 59                  <1> 	pop	ecx
  4994 00001F5F 5B                  <1> 	pop	ebx
  4995 00001F60 5E                  <1> 	pop	esi
  4996 00001F61 5F                  <1> 	pop	edi
  4997 00001F62 C3                  <1> 	retn	
  4998                              <1> 
  4999                              <1> ;RET_2:
  5000                              <1> ;	retf	4			; BACK TO CALLER
  5001                              <1> 
  5002                              <1> A1:
  5003                              <1> 	; 11/07/2022
  5004                              <1> 	;sti				; ENABLE INTERRUPTS
  5005                              <1> 	;cmp	dl, (80h + S_MAX_FILE - 1)
  5006                              <1> 	;ja	short RET_2
  5007                              <1> 	
  5008                              <1> 	; 18/01/2015
  5009                              <1> 	;;or	ah, ah
  5010                              <1> 	;or	al, al ; 11/07/2022 (reset function)
  5011                              <1> 	;jz	short A3 ; 08/07/2022
  5012                              <1> 	
  5013                              <1> 	;;cmp	ah, 5  ; Alternate reset
  5014                              <1> 	;cmp	al, 5  ; 11/07/2022
  5015                              <1> 	;je	short A2
  5016                              <1> 	
  5017                              <1> 	; 11/07/2022 - no need to check
  5018                              <1> 	;		 (only kernel calls diskio functions)
  5019                              <1> 	;;cmp	ah, M1L/4 ; cmp ah, 6
  5020                              <1> 	;jb	short A3
  5021                              <1> 	;; BAD COMMAND
  5022                              <1>         ;mov     byte [DISK_STATUS1], BAD_CMD
  5023                              <1> ;RET_2:
  5024                              <1> 	;retf	4
  5025                              <1> 
  5026                              <1> 	; 11/07/2022
  5027                              <1> 	;stc
  5028                              <1> 	;retn
  5029                              <1> A2:
  5030                              <1> 	;sub	ah, ah	; Reset
  5031                              <1> 	; 11/07/2022
  5032                              <1> 	;sub	al, al
  5033                              <1> A3:
  5034                              <1> 					; SAVE REGISTERS DURING OPERATION
  5035 00001F63 C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  5036                              <1> 	
  5037                              <1> 	; 11/07/2022
  5038                              <1> 	; 08/07/2022
  5039                              <1> 	;push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  5040                              <1> 	;push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  5041                              <1> 	;push	edx
  5042                              <1> 	;push	esi
  5043                              <1> 	;push	edi
  5044                              <1> 	
  5045 00001F67 E80D000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  5046                              <1> 
  5047 00001F6C C9                  <1> 	leave	; 11/07/2022
  5048                              <1> 	
  5049 00001F6D 8A25[BB610000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  5050 00001F73 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  5051 00001F76 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  5052                              <1> 	
  5053                              <1> 	;pop	edi			; RESTORE REGISTERS
  5054                              <1> 	;pop	esi
  5055                              <1>       	;pop	edx
  5056                              <1> 	;pop	ecx
  5057                              <1> 	;pop	ebx
  5058                              <1> 	
  5059                              <1> 	;leave				; ADJUST (ESP) AND RESTORE (EBP)
  5060                              <1> 	
  5061                              <1> 	; 11/07/2022
  5062                              <1> 	;retf	4			; THROW AWAY SAVED FLAGS
  5063                              <1> 
  5064 00001F77 EBE4                <1> 	jmp	short DISK_IO_RTN
  5065                              <1> 
  5066                              <1> DISK_IO_CONT:
  5067                              <1> 	; 17/07/2022
  5068                              <1> 	; 11/07/2022
  5069                              <1> 	;	INPUT:
  5070                              <1> 	;	    AL = 0 : reset
  5071                              <1> 	;	    AL = 1 : read
  5072                              <1> 	;	    Al = 2 : write
  5073                              <1> 	; 	
  5074                              <1> 	; 10/07/2022
  5075                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5076                              <1> SU0:
  5077 00001F79 C605[BB610000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  5078                              <1> 	; 10/07/2022
  5079 00001F80 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  5080                              <1> 
  5081 00001F82 8A1D[BC610000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  5082 00001F88 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  5083                              <1> 					; (get drive number as 0 to 3)
  5084 00001F8B 38D3                <1> 	cmp	bl, dl
  5085                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  5086                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5087                              <1> 	; 24/12/2021
  5088 00001F8D 7705                <1> 	ja	short su0_su1
  5089 00001F8F E98D000000          <1> 	jmp	BAD_COMMAND
  5090                              <1> su0_su1:
  5091                              <1>         ;;03/01/2015
  5092 00001F94 29DB                <1> 	sub	ebx, ebx
  5093 00001F96 88D3                <1> 	mov	bl, dl
  5094 00001F98 883D[D0610000]      <1> 	mov	[LBAMode], bh  ; 0
  5095                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  5096                              <1> 	;jz	short su1		; no
  5097                              <1> 	;inc	byte [LBAMode]
  5098                              <1> ;su1:
  5099                              <1> 	; 21/02/2015 (32 bit modification)
  5100                              <1> 	; 04/01/2015
  5101                              <1> 	;push	ax ; ***
  5102                              <1> 	; 24/12/2021
  5103 00001F9E 50                  <1> 	push	eax ; *** ; function (in AL) ; 11/07/2022
  5104                              <1> 	; 24/12/2021
  5105 00001F9F 52                  <1> 	push	edx ; *
  5106 00001FA0 50                  <1> 	push	eax ; function (in AL)	; 11/07/2022
  5107 00001FA1 E8C4030000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5108                              <1> 	; 02/02/2015
  5109 00001FA6 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  5110 00001FAA 66A3[425C0000]      <1> 	mov	[HF_PORT], ax
  5111 00001FB0 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  5112 00001FB4 668915[445C0000]    <1> 	mov	[HF_REG_PORT], dx
  5113 00001FBB 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  5114                              <1> 	; 23/02/2015
  5115 00001FBE A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5116 00001FC0 7406                <1> 	jz 	short su1
  5117 00001FC2 FE05[D0610000]      <1> 	inc	byte [LBAMode] ; 1 
  5118                              <1> su1: 	 
  5119 00001FC8 C0E804              <1> 	shr 	al, 4
  5120 00001FCB 2401                <1> 	and	al, 1			
  5121 00001FCD A2[465C0000]        <1> 	mov	[hf_m_s], al 
  5122                              <1> 	;
  5123                              <1> 	; 03/01/2015
  5124 00001FD2 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5125                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  5126 00001FD5 EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  5127                              <1> 					; Control Byte: (= 08h, here)
  5128                              <1> 					; bit 0 - 0
  5129                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5130                              <1> 					; bit 2 - SRST (software RESET)
  5131                              <1> 					; bit 3 - use extra heads (8 to 15)
  5132                              <1> 					;         -always set to 1-	
  5133                              <1> 					; (bits 3 to 7 are reserved
  5134                              <1> 					;          for ATA devices)
  5135 00001FD6 8A25[BD610000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5136 00001FDC 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  5137 00001FDF 08C4                <1> 	or	ah, al
  5138 00001FE1 8825[BD610000]      <1> 	mov	[CONTROL_BYTE], ah	
  5139                              <1> 	; 04/01/2015
  5140                              <1> 	;pop	ax
  5141                              <1> 	; 24/12/2021
  5142 00001FE7 58                  <1> 	pop	eax ; function (in AL) ; 11/07/2022
  5143                              <1> 	;pop	dx ; * ;; 14/02/2015
  5144                              <1> 	; 24/12/2021
  5145 00001FE8 5A                  <1> 	pop	edx ; *
  5146                              <1> 	;and	ah, ah	; Reset function ?
  5147 00001FE9 20C0                <1> 	and	al, al	; 11/07/2022
  5148 00001FEB 7506                <1> 	jnz	short su2
  5149                              <1> 	;pop	ax ; ***
  5150                              <1> 	; 24/12/2021
  5151 00001FED 58                  <1> 	pop	eax ; *** 	
  5152                              <1> 	;;pop	bx
  5153 00001FEE E9E4000000          <1>         jmp     DISK_RESET
  5154                              <1> su2:
  5155                              <1> 	; 11/07/2022
  5156                              <1> 	; ecx = sector address (lba)
  5157                              <1> 	;  dl = hard disk drive number (80h, 81h .. 83h)	 
  5158                              <1> 	;  al = function (0 = read, 1 = write)	
  5159                              <1> 
  5160 00001FF3 803D[D0610000]00    <1> 	cmp	byte [LBAMode], 0
  5161 00001FFA 7620                <1> 	jna	short su3 ; convert LBA address to CHS parameters
  5162                              <1> 	
  5163                              <1> ;	; 02/02/2015 (LBA read/write function calls)
  5164                              <1> ;	;cmp	ah, 1Bh
  5165                              <1> ;	cmp	ah, 3 ; 08/07/2022
  5166                              <1> ;	jb	short lbarw1
  5167                              <1> ;	;;cmp	ah, 1Ch
  5168                              <1> ;	;cmp	ah, 4 ; 08/07/2022 
  5169                              <1> ;	;ja 	short invldfnc
  5170                              <1> ;	;;pop	dx ; * ; 14/02/2015
  5171                              <1> ;	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5172                              <1> 
  5173 00001FFC 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5174                              <1> 
  5175                              <1> 	; 11/07/2022
  5176                              <1> 	;; 14/02/2015
  5177                              <1> 	;mov	cl, dl ; 14/02/2015
  5178                              <1> 
  5179                              <1> 	;;mov	dx, bx
  5180                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5181                              <1> 	;;mov	bx, di
  5182                              <1> 	;mov	si, di ; Buffer offset
  5183                              <1> 
  5184                              <1> 	; 11/07/2022
  5185                              <1> 	;jmp	short lbarw2
  5186                              <1> 
  5187                              <1> ;lbarw1:
  5188                              <1> ;	; convert CHS to LBA
  5189                              <1> ;	;
  5190                              <1> ;	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5191                              <1> ;	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5192                              <1> ;	;	+ Sector - 1
  5193                              <1> ;	;push	dx ; * ;; 14/02/2015
  5194                              <1> ;	; 24/12/2021
  5195                              <1> ;	push	edx ; *
  5196                              <1> ;	;xor	dh, dh
  5197                              <1> ;	xor	edx, edx
  5198                              <1> ;	mov	dl, [ebx+14]	; sectors per track (logical)
  5199                              <1> ;	;xor	ah, ah
  5200                              <1> ;	xor	eax, eax
  5201                              <1> ;	mov	al, [ebx+2]	; heads (logical) 
  5202                              <1> ;	dec	al
  5203                              <1> ;	;inc	ax		; 0 =  256
  5204                              <1> ;	inc	eax ; 24/12/2021
  5205                              <1> ;	mul 	dx
  5206                              <1> ;		; AX = # of Heads * Sectors/Track
  5207                              <1> ;	mov	dx, cx
  5208                              <1> ;	;and	cx, 3Fh	 ; sector (1 to 63)
  5209                              <1> ;	and	ecx, 3fh
  5210                              <1> ;	xchg	dl, dh
  5211                              <1> ;	shr	dh, 6
  5212                              <1> ;		; DX = cylinder (0 to 1023)
  5213                              <1> ;	;mul 	dx
  5214                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder
  5215                              <1> ;	mul	edx
  5216                              <1> ;	dec	cl  ; sector - 1
  5217                              <1> ;	;add	ax, cx
  5218                              <1> ;	;adc	dx, 0
  5219                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  5220                              <1> ;	add	eax, ecx
  5221                              <1> ;	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5222                              <1> ;	; 24/12/2021
  5223                              <1> ;	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  5224                              <1> ;	;push	dx
  5225                              <1> ;	;push	ax
  5226                              <1> ;	push	eax
  5227                              <1> ;	mov	al, [ebx+14]  ; sectors per track (logical)	
  5228                              <1> ;	mul	ch
  5229                              <1> ;		; AX = Head * Sectors/Track
  5230                              <1> ;	cwd
  5231                              <1> ;	;pop	dx
  5232                              <1> ;	pop	edx
  5233                              <1> ;	;add	ax, dx
  5234                              <1> ;	;pop	dx
  5235                              <1> ;	;adc	dx, 0 ; add carry bit
  5236                              <1> ;	add	eax, edx
  5237                              <1> ;
  5238                              <1> ;lbarw2:
  5239                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5240                              <1> 	
  5241 00001FFE 29D2                <1> 	sub	edx, edx ; 21/02/2015
  5242                              <1> 	
  5243                              <1> 	; 11/07/2022
  5244                              <1> 	;mov	dl, cl ; 21/02/2015
  5245                              <1>         
  5246 00002000 C645F800            <1> 	mov     byte [CMD_BLOCK], 0 ; Features Register
  5247                              <1> 				; NOTE: Features register (1F1h, 171h)
  5248                              <1> 				; is not used for ATA device R/W functions. 
  5249                              <1> 				; It is old/obsolete 'write precompensation'
  5250                              <1> 				; register and error register
  5251                              <1> 				; for old ATA/IDE devices.
  5252                              <1> 	; 18/01/2014
  5253                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  5254 00002004 8A0D[465C0000]      <1> 	mov	cl, [hf_m_s]
  5255                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  5256                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  5257                              <1> 				; bit 6 = 1 = LBA mode
  5258                              <1> 				; bit 7 = 1
  5259 0000200A 80C90E              <1> 	or	cl, 0Eh ; 1110b
  5260                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  5261 0000200D 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  5262 00002012 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  5263                              <1> 	;or	dh, ch
  5264 00002015 09C8                <1> 	or	eax, ecx	
  5265                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  5266                              <1> 				  ; (Sector Number Register)
  5267                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  5268                              <1> 				  ; (Cylinder Low Register)
  5269                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  5270                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  5271                              <1> 				  ; (Cylinder High Register)
  5272                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  5273                              <1> 				  ; (Drive/Head Register)
  5274                              <1> 	
  5275                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  5276 00002017 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  5277                              <1> 	;14/02/2015
  5278                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  5279 0000201A EB3D                <1> 	jmp	short su4
  5280                              <1> su3:
  5281                              <1> 	; 02/02/2015 
  5282                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  5283                              <1> 	;cmp 	ah, 14h
  5284                              <1> 	;jna 	short chsfnc
  5285                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5286                              <1> 	;cmp	ah, 2
  5287                              <1> 	;jna	short chsfnc
  5288                              <1> 	; 11/07/2022 
  5289                              <1> 	; (al = function, read = 1 or write = 2)
  5290 0000201C 3C02                <1> 	cmp	al, 2 
  5291 0000201E 760B                <1> 	jna	short chsfnc
  5292                              <1> invldfnc:
  5293                              <1>         ; 14/02/2015  
  5294                              <1> 	;pop	es ; **
  5295                              <1>         ;pop	ax ; ***
  5296                              <1>         ; 24/12/2021
  5297 00002020 58                  <1> 	pop	eax ; ***
  5298                              <1> 	;;jmp	short BAD_COMMAND_POP
  5299                              <1> 	; 11/07/2022
  5300                              <1>         ;jmp     short BAD_COMMAND
  5301                              <1> 
  5302                              <1> 	; 11/07/2022
  5303                              <1> BAD_COMMAND:
  5304 00002021 C605[BB610000]01    <1> 	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5305                              <1> 	;mov	al, 0
  5306 00002028 28C0                <1> 	sub	al, al ; 0
  5307 0000202A C3                  <1> 	retn
  5308                              <1> 
  5309                              <1> chsfnc:	
  5310 0000202B 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5311                              <1> 	;shr	ax, 2
  5312                              <1> 	; 17/07/2022
  5313 0000202F C1E802              <1> 	shr	eax, 2
  5314 00002032 8845F8              <1> 	mov	[CMD_BLOCK], al
  5315                              <1> 	;
  5316                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5317                              <1> 	;;push	edx ; *
  5318                              <1> 	;;mov	dx, [HF_REG_PORT]
  5319                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5320                              <1> 	;;pop	edx ; * 
  5321                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5322                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5323                              <1> 	;;or	ah, al
  5324                              <1> 	;;mov	[CONTROL_BYTE], ah
  5325                              <1> 	;
  5326 00002035 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5327 00002037 243F                <1> 	and	al, 3Fh
  5328 00002039 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5329 0000203C 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5330 0000203F 88C8                <1> 	mov	al, cl
  5331 00002041 C0E806              <1> 	shr	al, 6
  5332 00002044 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5333                              <1> 	;;05/01/2015
  5334                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5335 00002047 A0[465C0000]        <1> 	mov	al, [hf_m_s]
  5336 0000204C C0E004              <1> 	shl	al, 4
  5337 0000204F 80E60F              <1> 	and	dh, 0Fh			; HEAD NUMBER
  5338 00002052 08F0                <1> 	or	al, dh
  5339 00002054 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5340 00002056 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5341                              <1> su4:
  5342                              <1> 	;; 14/02/2015
  5343                              <1>         ;;pop	ax
  5344                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5345                              <1>         ;;push	ax
  5346                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5347                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5348                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5349                              <1> 	;pop	ax ; ***
  5350                              <1> 	; 24/12/2021
  5351 00002059 58                  <1> 	pop	eax ; *** ; function (in AL) ; 11/07/2022
  5352                              <1> 	
  5353                              <1> 	;mov	[CMD_BLOCK+1], al
  5354 0000205A C645F901            <1>         mov	byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w)
  5355                              <1> 
  5356                              <1> 	; 11/07/2022
  5357                              <1> 	;mov	ebx, esi
  5358                              <1> 	; (esi = buffer address)	
  5359                              <1> 
  5360 0000205E 3C02                <1> 	cmp	al, 2
  5361 00002060 742D                <1> 	je	short DISK_WRITE
  5362                              <1> 
  5363                              <1> 	;jmp	short DISK_READ
  5364                              <1> 
  5365                              <1> ;	;xor	ebx, ebx
  5366                              <1> ;	;mov	bl, ah
  5367                              <1> ;
  5368                              <1> ;       ;xor	bh, bh
  5369                              <1> ;       ;sal	bx, 1
  5370                              <1> ;       sal	bx, 2	; 32 bit offset (21/02/2015)
  5371                              <1> ;	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5372                              <1> ;       ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5373                              <1> ;       ;;jnb	short BAD_COMMAND_POP
  5374                              <1> ;   	; 08/07/2022
  5375                              <1> ;	;cmp	ebx, M1L
  5376                              <1> ;	;jnb	short BAD_COMMAND
  5377                              <1> ;
  5378                              <1> ;	xchg	ebx, esi
  5379                              <1> ;
  5380                              <1> ;	;;;pop	ax			; RESTORE AX
  5381                              <1> ;	;;;pop	bx			; AND DATA ADDRESS
  5382                              <1> ;	
  5383                              <1> ;	;;push	cx
  5384                              <1> ;	;;push	ax			; ADJUST ES:BX
  5385                              <1> ;	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5386                              <1> ;	;shr	cx, 4
  5387                              <1> ;	;mov	ax, es
  5388                              <1> ;	;add	ax, cx
  5389                              <1> ;	;mov	es, ax
  5390                              <1> ;	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5391                              <1> ;	;;pop	ax
  5392                              <1> ;	;;pop	cx
  5393                              <1> ;
  5394                              <1> ;	jmp	dword [esi+M1]
  5395                              <1> 
  5396                              <1> ;;BAD_COMMAND_POP:
  5397                              <1> ;;	pop	ax
  5398                              <1> ;;	pop	bx
  5399                              <1> ;
  5400                              <1> ;	; 11/07/2022
  5401                              <1> ;BAD_COMMAND:
  5402                              <1> ;	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5403                              <1> ;	;mov	al, 0
  5404                              <1> ;	sub	al, al ; 0
  5405                              <1> ;	retn
  5406                              <1> 
  5407                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5408                              <1> 
  5409                              <1> ;----------------------------------------
  5410                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5411                              <1> ;----------------------------------------
  5412                              <1> ; 
  5413                              <1> DISK_READ:
  5414 00002062 C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5415                              <1>         ;jmp	COMMANDI
  5416                              <1> 
  5417                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5418                              <1> 
  5419                              <1> ;----------------------------------------
  5420                              <1> ; COMMANDI				:
  5421                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5422                              <1> ;	NSECTOR RETURNS ZERO		:
  5423                              <1> ;----------------------------------------
  5424                              <1> COMMANDI:
  5425                              <1> 	; 11/07/2022 
  5426                              <1> 	;	(check 64K boundary is not needed)
  5427                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5428                              <1> 	;jc	short CMD_ABORT
  5429                              <1> 	
  5430                              <1> 	;mov	di, bx
  5431                              <1> 	; 11/07/2022
  5432                              <1> 	; (esi = buffer address)
  5433                              <1> 	;mov	edi, ebx ; 21/02/2015
  5434 00002066 89F7                <1> 	mov	edi, esi ; 11/07/2022	
  5435                              <1> 
  5436 00002068 E8A8010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5437 0000206D 751F                <1> 	jnz	short CMD_ABORT
  5438                              <1> CMD_I1:
  5439 0000206F E813020000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5440 00002074 7518                <1> 	jnz	short TM_OUT		; TIME OUT
  5441                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5442                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5443 00002076 29C9                <1> 	sub	ecx, ecx
  5444 00002078 FEC5                <1> 	inc	ch
  5445                              <1> 	; ecx = 256
  5446                              <1> 	;mov	dx, HF_PORT
  5447 0000207A 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  5448 00002081 FA                  <1> 	cli
  5449 00002082 FC                  <1> 	cld
  5450 00002083 F3666D              <1> 	rep	insw			; GET THE SECTOR
  5451 00002086 FB                  <1> 	sti
  5452                              <1> 	
  5453                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5454                              <1> 	;jz	short CMD_I3
  5455                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5456                              <1> 	;jc	short TM_OUT
  5457                              <1> 	;;mov	dx, HF_PORT
  5458                              <1> 	;mov	dx,[HF_PORT]
  5459                              <1> 	;xor	ecx, ecx	
  5460                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5461                              <1> 	;mov	cl, 4
  5462                              <1> ;CMD_I2: 
  5463                              <1> 	;inc	al, dx
  5464                              <1> 	;mov 	[edi], al ; 21/02/2015
  5465                              <1> 	;inc	edi
  5466                              <1> 	;loop	CMD_I2
  5467                              <1> CMD_I3: 
  5468 00002087 E817010000          <1> 	call	CHECK_STATUS
  5469 0000208C 7500                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5470                              <1> 	; 11/07/2022
  5471                              <1> 	; (sector count = 1)
  5472                              <1> 	;dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5473                              <1> 	;jnz	SHORT CMD_I1
  5474                              <1> CMD_ABORT:
  5475                              <1> TM_OUT: 
  5476 0000208E C3                  <1> 	retn
  5477                              <1> 
  5478                              <1> ;---------------------------------------------------
  5479                              <1> 
  5480                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5481                              <1> 
  5482                              <1> ;----------------------------------------
  5483                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5484                              <1> ;----------------------------------------
  5485                              <1> 
  5486                              <1> DISK_WRITE:
  5487 0000208F C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5488                              <1>         ;JMP	COMMANDO
  5489                              <1> 
  5490                              <1> ; 16/07/2022
  5491                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5492                              <1> 
  5493                              <1> ;----------------------------------------
  5494                              <1> ; COMMANDO				:
  5495                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5496                              <1> ;	NSECTOR RETURNS ZERO		:
  5497                              <1> ;----------------------------------------
  5498                              <1> COMMANDO:
  5499                              <1> 	; 11/07/2022 
  5500                              <1> 	;	(check 64K boundary is not needed)
  5501                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5502                              <1> 	;jc	short CMD_ABORT
  5503                              <1> CMD_OF:
  5504                              <1> 	; 11/07/2022
  5505                              <1> 	; (esi = ebx = buffer address)
  5506                              <1> 	;mov	esi, ebx ; 21/02/2015
  5507 00002093 E87D010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5508 00002098 75F4                <1> 	jnz	short CMD_ABORT
  5509 0000209A E83F020000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5510 0000209F 72ED                <1> 	jc	short TM_OUT		; TOO LONG
  5511                              <1> CMD_O1:
  5512                              <1> 	; 16/07/2022
  5513 000020A1 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  5514                              <1> 
  5515                              <1> 	; 10/07/2022
  5516                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5517 000020A8 31C9                <1> 	xor	ecx, ecx
  5518 000020AA FEC5                <1> 	inc	ch
  5519                              <1> 	; ecx = 256
  5520 000020AC FA                  <1> 	cli
  5521 000020AD FC                  <1> 	cld
  5522 000020AE F3666F              <1> 	rep	outsw
  5523 000020B1 FB                  <1> 	sti
  5524                              <1> 
  5525                              <1> 	; 10/07/2022
  5526                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5527                              <1> 	;jz	short CMD_O3
  5528                              <1> 	;
  5529                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5530                              <1> 	;jc	short TM_OUT
  5531                              <1> 	;;mov	dx, HF_PORT
  5532                              <1> 	;mov	dx, [HF_PORT]
  5533                              <1> 	;sub	ecx, ecx	
  5534                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5535                              <1> 	;mov	cl, 4
  5536                              <1> ;CMD_O2:
  5537                              <1> 	;;lodsb
  5538                              <1> 	;mov	al, [esi]
  5539                              <1> 	;out	dx, al
  5540                              <1> 	;inc	esi
  5541                              <1> 	;loop	CMD_O2
  5542                              <1> 
  5543                              <1> CMD_O3:
  5544 000020B2 E8D0010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5545 000020B7 75D5                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5546 000020B9 E8E5000000          <1> 	call	CHECK_STATUS
  5547 000020BE 75CE                <1> 	jnz	short CMD_ABORT
  5548                              <1> 
  5549                              <1> 	; 11/07/2022
  5550                              <1> 	; (sector count = 1)
  5551                              <1> 	;test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5552                              <1> 	;jnz	short CMD_O1
  5553                              <1> 	
  5554                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5555 000020C0 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  5556 000020C7 80C202              <1> 	add	dl, 2
  5557                              <1> 	;inc	dl
  5558                              <1> 	;inc	dl
  5559 000020CA EC                  <1> 	in	al, dx			;
  5560 000020CB A8FF                <1> 	test	al, 0FFh 		;
  5561 000020CD 7407                <1> 	jz	short CMD_O4		; COUNT = 0  OK
  5562 000020CF C605[BB610000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5563                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5564                              <1> CMD_O4:
  5565 000020D6 C3                  <1> 	retn
  5566                              <1> 
  5567                              <1> ; 10/07/2022
  5568                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5569                              <1> 
  5570                              <1> ;----------------------------------------
  5571                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5572                              <1> ;----------------------------------------
  5573                              <1> 
  5574                              <1> ; 18-1-2015 : one controller reset (not other one)
  5575                              <1> 
  5576                              <1> DISK_RESET:
  5577 000020D7 FA                  <1> 	cli
  5578 000020D8 E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5579                              <1> 	;JMP	$+2
  5580                              <1> 	IODELAY
  2191 000020DA EB00                <2>  jmp short $+2
  2192 000020DC EB00                <2>  jmp short $+2
  5581                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5582 000020DE 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5583 000020E0 E6A1                <1> 	out	INTB01, al
  5584 000020E2 FB                  <1> 	sti				; START INTERRUPTS
  5585                              <1> 	; 14/02/2015
  5586                              <1> 	;mov	di, dx
  5587                              <1> 	; 24/12/2021
  5588 000020E3 89D7                <1> 	mov	edi, edx	
  5589                              <1> 	; 04/01/2015
  5590                              <1> 	;xor	di,di
  5591                              <1> drst0:
  5592 000020E5 B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5593                              <1> 	;mov	dx, HF_REG_PORT
  5594 000020E7 668B15[445C0000]    <1> 	mov	dx, [HF_REG_PORT]
  5595 000020EE EE                  <1> 	out	dx, al			; RESET
  5596                              <1> ;	mov	cx, 10			; DELAY COUNT
  5597                              <1> ;DRD:	dec	cx
  5598                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5599                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5600                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5601                              <1> 	; 10/07/2022
  5602 000020EF 29C9                <1> 	sub	ecx, ecx
  5603 000020F1 B102                <1> 	mov	cl, 2
  5604 000020F3 E89BF2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5605                              <1>                                         ; 40 micro seconds)
  5606 000020F8 A0[BD610000]        <1> 	mov	al, [CONTROL_BYTE]
  5607 000020FD 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5608 000020FF EE                  <1> 	out	dx, al			; TURN RESET OFF
  5609 00002100 E8B2010000          <1> 	call	NOT_BUSY
  5610 00002105 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5611 00002107 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  5612 0000210E FEC2                <1> 	inc	dl  ; HF_PORT+1
  5613                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5614                              <1>         ;mov	cl, 10
  5615                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5616                              <1> 	; 10/07/2022
  5617                              <1> 	;xor	ecx, ecx
  5618 00002110 B10A                <1> 	mov	cl, 10 
  5619                              <1> drst1:
  5620 00002112 EC                  <1> 	in	al, dx			; GET RESET STATUS
  5621 00002113 3C01                <1> 	cmp	al, 1
  5622                              <1> 	; 04/01/2015
  5623 00002115 740C                <1> 	jz	short drst2
  5624                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5625                              <1>         	; Drive/Head Register - bit 4
  5626                              <1> 	;loop	drst1
  5627                              <1> 	; 10/07/2022
  5628 00002117 FEC9                <1> 	dec	cl
  5629 00002119 75F7                <1> 	jnz	short drst1
  5630                              <1> DRERR:	
  5631 0000211B C605[BB610000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5632 00002122 C3                  <1> 	retn
  5633                              <1> drst2:
  5634                              <1> 	; 14/02/2015
  5635                              <1> 	;mov	dx, di
  5636                              <1> 	; 24/12/2021
  5637 00002123 89FA                <1> 	mov	edx, edi
  5638                              <1> ;drst3:
  5639                              <1> ;	; 05/01/2015
  5640                              <1> ;	shl 	di, 1
  5641                              <1> ;	; 04/01/2015
  5642                              <1> ;	mov	ax, [di+hd_cports]
  5643                              <1> ;	cmp	ax, [HF_REG_PORT]
  5644                              <1> ;	je	short drst4
  5645                              <1> ;	mov	[HF_REG_PORT], ax
  5646                              <1> ;	; 03/01/2015
  5647                              <1> ;	mov	ax, [di+hd_ports]
  5648                              <1> ;       mov     [HF_PORT], ax
  5649                              <1> ;	; 05/01/2014
  5650                              <1> ;	shr	di, 1
  5651                              <1> ;	; 04/01/2015
  5652                              <1> ;	jmp	short drst0	; reset other controller
  5653                              <1> ;drst4:
  5654                              <1> ;	; 05/01/2015
  5655                              <1> ;	shr	di, 1
  5656                              <1> ;	mov	al, [di+hd_dregs]
  5657                              <1> ;	and	al, 10h ; bit 4 only
  5658                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5659                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5660                              <1> 	;
  5661 00002125 A0[465C0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5662 0000212A A801                <1> 	test	al, 1
  5663                              <1> 	;jnz	short drst6
  5664 0000212C 7516                <1>         jnz     short drst4
  5665 0000212E 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5666                              <1> ;drst5:
  5667                              <1> drst3:
  5668 00002132 E813000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5669                              <1> 	;mov	dx, di
  5670 00002137 E8A3000000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5671                              <1> 	; 04/01/2014
  5672                              <1> ;	inc	di
  5673                              <1> ;	mov	dx, di
  5674                              <1> ;	cmp	dl, [HF_NUM]
  5675                              <1> ;	jb	short drst3
  5676                              <1> ;DRE:
  5677 0000213C C605[BB610000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5678 00002143 C3                  <1> 	retn
  5679                              <1> ;drst6:
  5680                              <1> drst4:		; Drive/Head Register - bit 4
  5681 00002144 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5682                              <1>         ;jmp    short drst5
  5683 00002148 EBE8                <1>         jmp     short drst3
  5684                              <1> 
  5685                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5686                              <1> 
  5687                              <1> ;----------------------------------------
  5688                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5689                              <1> ;----------------------------------------
  5690                              <1> 	; 03/01/2015
  5691                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5692                              <1> 	; logical sector per logical track
  5693                              <1> 	; and logical heads - 1 would be set but
  5694                              <1> 	; it is seen as it will be good
  5695                              <1> 	; if physical parameters will be set here
  5696                              <1> 	; because, number of heads <= 16.
  5697                              <1> 	; (logical heads usually more than 16)
  5698                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5699                              <1> 	;	== INT 13h physical parameters
  5700                              <1> 
  5701                              <1> ;INIT_DRV:
  5702                              <1> ;	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5703                              <1> ;	call	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5704                              <1> ;	mov	al, [es:bx+2]		; GET NUMBER OF HEADS
  5705                              <1> ;	dec	al			; CONVERT TO 0-INDEX
  5706                              <1> ;	mov	ah, [CMD_BLOCK+5] 	; GET SDH REGISTER
  5707                              <1> ;	and	ah, 0F0h 		; CHANGE HEAD NUMBER
  5708                              <1> ;	or	ah, al			; TO MAX HEAD
  5709                              <1> ;	mov	[CMD_BLOCK+5], ah
  5710                              <1> ;	mov	al, [es:bx+14]		; MAX SECTOR NUMBER
  5711                              <1> ;	mov	[CMD_BLOCK+1], al
  5712                              <1> ;	sub	ax, ax
  5713                              <1> ;	mov	[CMD_BLOCK+3], al 	; ZERO FLAGS
  5714                              <1> ;	call	COMMAND 		; TELL CONTROLLER
  5715                              <1> ;	jnz	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5716                              <1> ;	call	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5717                              <1> ;	jnz	short INIT_EXIT		; TIME OUT
  5718                              <1> ;	call	CHECK_STATUS
  5719                              <1> ;INIT_EXIT:
  5720                              <1> ;	retn
  5721                              <1> 
  5722                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5723                              <1> 
  5724                              <1> ; 04/01/2015
  5725                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5726                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5727                              <1> INIT_DRV:
  5728                              <1> 	;xor	ah, ah
  5729 0000214A 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5730 0000214C B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5731 0000214E 3825[D0610000]      <1>         cmp     [LBAMode], ah   ; 0
  5732 00002154 7702                <1> 	ja	short idrv0
  5733 00002156 B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5734                              <1> idrv0:
  5735                              <1> 	; DL = drive number (0 based)
  5736 00002158 E80D020000          <1> 	call	GET_VEC
  5737                              <1> 	;push	bx
  5738 0000215D 53                  <1> 	push	ebx ; 21/02/2015
  5739                              <1> 	;add	bx, ax
  5740 0000215E 01C3                <1> 	add	ebx, eax
  5741                              <1> 	;; 05/01/2015
  5742 00002160 8A25[465C0000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5743                              <1> 	;;and 	ah, 1 
  5744 00002166 C0E404              <1> 	shl	ah, 4
  5745 00002169 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5746                              <1> 	;mov	al, [es:bx]
  5747 0000216C 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5748 0000216E FEC8                <1> 	dec	al	 ; last head number 
  5749                              <1> 	;and	al, 0Fh
  5750 00002170 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5751                              <1> 	;
  5752 00002172 C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5753 00002176 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5754                              <1> 	;pop	bx
  5755 00002179 5B                  <1> 	pop	ebx
  5756 0000217A 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5757 0000217C B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5758 0000217E 803D[D0610000]00    <1> 	cmp	byte [LBAMode], 0
  5759 00002185 7702                <1> 	ja	short idrv1
  5760 00002187 B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5761                              <1> idrv1:
  5762                              <1> 	;xor	ah, ah
  5763                              <1> 	;add	bx, ax
  5764 00002189 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5765                              <1> 	;mov	al, [es:bx]
  5766                              <1> 			; sector number
  5767 0000218B 8A03                <1> 	mov	al, [ebx]
  5768 0000218D 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5769 00002190 28C0                <1> 	sub	al, al
  5770 00002192 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5771 00002195 E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5772 0000219A 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5773 0000219C E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5774 000021A1 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5775                              <1> 	;call	CHECK_STATUS
  5776                              <1> 	;jmp	short CHECK_STATUS
  5777                              <1> ;INIT_EXIT:
  5778                              <1> 	;retn
  5779                              <1> 
  5780                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5781                              <1> 
  5782                              <1> ;----------------------------------------
  5783                              <1> ;	CHECK FIXED DISK STATUS 	:
  5784                              <1> ;----------------------------------------
  5785                              <1> CHECK_STATUS:
  5786 000021A3 E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5787                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5788                              <1> 	; 10/07/2022
  5789 000021A8 7510                <1> 	jnz	short CHECK_S2
  5790 000021AA A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5791 000021AC 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5792 000021AE E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5793                              <1> CHECK_S1:
  5794 000021B3 803D[BB610000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5795                              <1> CHECK_S2:
  5796                              <1> INIT_EXIT:	; 10/07/2022
  5797 000021BA C3                  <1> 	retn
  5798                              <1> 
  5799                              <1> ;----------------------------------------
  5800                              <1> ;	TEST DISK READY      (AH = 10H) :
  5801                              <1> ;----------------------------------------
  5802                              <1> 
  5803                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5804 000021BB E8F7000000          <1> 	call	NOT_BUSY
  5805 000021C0 751C                <1> 	jnz	short TR_EX
  5806 000021C2 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5807 000021C5 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  5808 000021CC 80C206              <1> 	add	dl,6
  5809 000021CF EE                  <1> 	out	dx, al
  5810 000021D0 E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5811 000021D5 7507                <1> 	jnz	short TR_EX
  5812 000021D7 C605[BB610000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5813                              <1> TR_EX:	
  5814 000021DE C3                  <1> 	retn
  5815                              <1> 
  5816                              <1> ;----------------------------------------
  5817                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5818                              <1> ;----------------------------------------
  5819                              <1> 
  5820                              <1> HDISK_RECAL:
  5821 000021DF C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5822 000021E3 E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5823 000021E8 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5824 000021EA E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5825 000021EF 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5826 000021F1 E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5827 000021F6 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5828                              <1> RECAL_X:
  5829 000021F8 E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5830 000021FD 803D[BB610000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5831 00002204 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5832 00002206 C605[BB610000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5833                              <1> RECAL_EXIT:
  5834 0000220D 803D[BB610000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5835 00002214 C3                  <1> 	retn
  5836                              <1> 
  5837                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5838                              <1> 
  5839                              <1> ;--------------------------------------------------------
  5840                              <1> ; COMMAND						:
  5841                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5842                              <1> ; OUTPUT						:
  5843                              <1> ;	BL = STATUS					:
  5844                              <1> ;	BH = ERROR REGISTER				:
  5845                              <1> ;--------------------------------------------------------
  5846                              <1> 
  5847                              <1> COMMAND:
  5848                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5849                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5850                              <1> COMMAND1:
  5851                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5852 00002215 E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5853                              <1> 	;;pop	ecx
  5854                              <1> 	;pop	ebx ; 10/07/2022
  5855 0000221A 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5856 0000221C 803D[BB610000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5857                              <1> 	;jz	short CMD_TIMEOUT
  5858                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5859                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5860 00002223 7507                <1> 	jne	short COMMAND4
  5861                              <1> CMD_TIMEOUT:
  5862 00002225 C605[BB610000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5863                              <1> COMMAND4:
  5864                              <1> 	;;pop	ebx ; 10/07/2022
  5865 0000222C 803D[BB610000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5866 00002233 C3                  <1> 	retn
  5867                              <1> COMMAND2:
  5868                              <1> 	;;pop	ebx ; 10/07/2022
  5869                              <1> 	;push	edi ; 10/07/2022
  5870 00002234 C605[B6610000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5871 0000223B FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5872 0000223C E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5873                              <1> 	;and	al, 0BFh
  5874 0000223E 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5875                              <1> 	;JMP	$+2
  5876                              <1> 	IODELAY
  2191 00002240 EB00                <2>  jmp short $+2
  2192 00002242 EB00                <2>  jmp short $+2
  5877 00002244 E6A1                <1> 	out	INTB01, al
  5878 00002246 E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5879 00002248 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5880                              <1> 	;JMP	$+2
  5881                              <1> 	IODELAY
  2191 0000224A EB00                <2>  jmp short $+2
  2192 0000224C EB00                <2>  jmp short $+2
  5882 0000224E E621                <1> 	out	INTA01, al
  5883 00002250 FB                  <1> 	sti
  5884                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5885                              <1> 	; 10/07/2022
  5886 00002251 31C9                <1> 	xor	ecx, ecx
  5887                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5888 00002253 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  5889 0000225A FEC2                <1> 	inc	dl
  5890 0000225C F605[BD610000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5891 00002263 7411                <1> 	jz	short COMMAND3
  5892 00002265 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5893 00002268 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5894 0000226A 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5895 0000226C 7208                <1> 	jb	short COMMAND3
  5896 0000226E 3C40                <1> 	cmp	al, 40h
  5897 00002270 7704                <1> 	ja	short COMMAND3
  5898 00002272 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5899                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5900                              <1> COMMAND3:
  5901                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5902                              <1> 	; 10/07/2022
  5903 00002276 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5904 0000227A EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5905                              <1> 	IODELAY
  2191 0000227B EB00                <2>  jmp short $+2
  2192 0000227D EB00                <2>  jmp short $+2
  5906                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5907                              <1> 	; 10/07/2022
  5908 0000227F 41                  <1> 	inc	ecx
  5909                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5910 00002280 42                  <1> 	inc	edx   ; 10/07/2022	
  5911                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5912                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5913 00002281 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5914 00002284 72F0                <1> 	jb	short COMMAND3
  5915                              <1> 	;pop	edi ; 10/07/2022
  5916 00002286 C3                  <1> 	retn				; ZERO FLAG IS SET
  5917                              <1> 
  5918                              <1> ;CMD_TIMEOUT:
  5919                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5920                              <1> ;COMMAND4:
  5921                              <1> ;	pop	ebx
  5922                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5923                              <1> ;	retn
  5924                              <1> 
  5925                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5926                              <1> 
  5927                              <1> ;----------------------------------------
  5928                              <1> ;	WAIT FOR INTERRUPT		:
  5929                              <1> ;----------------------------------------
  5930                              <1> ;WAIT:
  5931                              <1> _WAIT:
  5932 00002287 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5933                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5934                              <1> 	;clc
  5935                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5936                              <1> 	;int	15h
  5937                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5938                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5939                              <1> 
  5940                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5941                              <1> 	;; 21/02/2015
  5942                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5943                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5944 00002288 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5945                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5946                              <1> ;-----	WAIT LOOP
  5947                              <1> 
  5948                              <1> WT1:	
  5949                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5950 0000228D F605[B6610000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5951                              <1> 	;loopz	WT1
  5952 00002294 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5953                              <1> 	;dec	bl
  5954                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5955                              <1> 
  5956                              <1> WT1_hi:
  5957 00002296 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5958 00002298 A810                <1> 	test	al, 10h			; transition on memory
  5959 0000229A 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5960                              <1> WT1_lo:
  5961 0000229C E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5962 0000229E A810                <1> 	test	al, 10h			
  5963 000022A0 74FA                <1> 	jz	short WT1_lo
  5964 000022A2 E2E9                <1> 	loop	WT1
  5965                              <1> 	;;or	bl, bl
  5966                              <1> 	;;jz	short WT2	
  5967                              <1> 	;;dec	bl
  5968                              <1> 	;;jmp	short WT1
  5969                              <1> 	;dec	bl
  5970                              <1> 	;jnz	short WT1	
  5971                              <1> WT2:	
  5972                              <1> 	; 10/07/2022
  5973                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5974 000022A4 B080                <1> 	mov	al, TIME_OUT
  5975 000022A6 EB07                <1> 	jmp	short WT4
  5976                              <1> WT3:
  5977                              <1> 	;mov	byte [DISK_STATUS1], 0
  5978                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5979 000022A8 28C0                <1> 	sub	al, al ; 0
  5980 000022AA A2[B6610000]        <1> 	mov	byte [HF_INT_FLAG], al
  5981                              <1> WT4:
  5982                              <1> NB2:	
  5983 000022AF A2[BB610000]        <1> 	mov	byte [DISK_STATUS1], al
  5984                              <1> 
  5985                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5986 000022B4 20C0                <1> 	and	al, al
  5987                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5988 000022B6 C3                  <1> 	retn
  5989                              <1> 
  5990                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5991                              <1> 
  5992                              <1> ;----------------------------------------
  5993                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5994                              <1> ;----------------------------------------
  5995                              <1> NOT_BUSY:
  5996 000022B7 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5997                              <1> 	;push	ebx
  5998                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5999 000022B8 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  6000 000022BF 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6001                              <1> 	;mov	bl, DELAY_1
  6002                              <1> 					; wait for 10 seconds
  6003                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6004                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6005                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6006 000022C2 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6007                              <1> 	;
  6008                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  6009                              <1> NB1:	
  6010 000022C7 EC                  <1> 	in	al, dx			; CHECK STATUS
  6011                              <1> 	;test	al, ST_BUSY
  6012 000022C8 2480                <1> 	and	al, ST_BUSY
  6013                              <1> 	;loopnz NB1
  6014 000022CA 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  6015                              <1> 	;dec	bl			
  6016                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  6017                              <1> 
  6018                              <1> NB1_hi: 
  6019 000022CC E461                <1> 	in	al, SYS1		; wait for hi to lo
  6020 000022CE A810                <1> 	test	al, 010h		; transition on memory
  6021 000022D0 75FA                <1> 	jnz	short NB1_hi		; refresh.
  6022                              <1> NB1_lo: 
  6023 000022D2 E461                <1> 	in	al, SYS1
  6024 000022D4 A810                <1> 	test	al, 010h
  6025 000022D6 74FA                <1> 	jz	short NB1_lo
  6026 000022D8 E2ED                <1> 	loop	NB1
  6027                              <1> 	;dec	bl
  6028                              <1> 	;jnz	short NB1
  6029                              <1> 	;
  6030                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6031                              <1> 	;;jb	short NB1
  6032                              <1> 	;
  6033                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  6034                              <1> 	;jmp	short NB3
  6035 000022DA B080                <1> 	mov	al, TIME_OUT
  6036                              <1> ;NB2:	
  6037 000022DC EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  6038                              <1> 
  6039                              <1> ;	;mov	byte [DISK_STATUS1], 0
  6040                              <1> ;;NB3:	
  6041                              <1> ;	;pop	ebx
  6042                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  6043                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  6044                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  6045                              <1> ;	retn
  6046                              <1> 
  6047                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6048                              <1> 
  6049                              <1> ;----------------------------------------
  6050                              <1> ;	WAIT FOR DATA REQUEST		:
  6051                              <1> ;----------------------------------------
  6052                              <1> WAIT_DRQ:
  6053                              <1> 	;mov	cx, DELAY_3
  6054                              <1> 	;mov	dx, HF_PORT+7
  6055 000022DE 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  6056 000022E5 80C207              <1> 	add	dl, 7
  6057                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  6058                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  6059                              <1> 					; (but it is written as 2000
  6060                              <1> 					; micro seconds in ATORGS.ASM file
  6061                              <1> 					; of Award Bios - 1999, D1A0622)
  6062 000022E8 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6063                              <1> WQ_1:
  6064 000022ED EC                  <1> 	in	al, dx			; GET STATUS
  6065 000022EE A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  6066 000022F0 7516                <1> 	jnz	short WQ_OK
  6067                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6068                              <1> WQ_hi:	
  6069 000022F2 E461                <1> 	in	al, SYS1		; wait for hi to lo
  6070 000022F4 A810                <1> 	test	al, 010h		; transition on memory
  6071 000022F6 75FA                <1> 	jnz	short WQ_hi		; refresh.
  6072                              <1> WQ_lo:  
  6073 000022F8 E461                <1> 	in	al, SYS1
  6074 000022FA A810                <1> 	test	al, 010h
  6075 000022FC 74FA                <1> 	jz	short WQ_lo
  6076 000022FE E2ED                <1> 	loop	WQ_1
  6077                              <1> 
  6078 00002300 C605[BB610000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  6079 00002307 F9                  <1> 	stc
  6080                              <1> WQ_OK:
  6081 00002308 C3                  <1> 	retn
  6082                              <1> ;WQ_OK:
  6083                              <1> 	;clc
  6084                              <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 STATUS BYTE	:
  6090                              <1> ;----------------------------------------
  6091                              <1> CHECK_ST:
  6092                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  6093 00002309 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]
  6094 00002310 80C207              <1> 	add	dl, 7
  6095 00002313 EC                  <1> 	in	al, dx
  6096 00002314 A2[B5610000]        <1> 	mov	[HF_STATUS], al
  6097                              <1> 	;mov	ah, 0
  6098 00002319 28E4                <1> 	sub	ah, ah ; 0
  6099 0000231B A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  6100 0000231D 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  6101 0000231F B4CC                <1> 	mov	ah, WRITE_FAULT
  6102 00002321 A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  6103 00002323 7514                <1> 	jnz	short CKST_EXIT
  6104 00002325 B4AA                <1> 	mov	ah, NOT_RDY
  6105 00002327 A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  6106 00002329 740E                <1> 	jz	short CKST_EXIT
  6107 0000232B B440                <1> 	mov	ah, BAD_SEEK
  6108 0000232D A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  6109 0000232F 7408                <1> 	jz	short CKST_EXIT
  6110 00002331 B411                <1> 	mov	ah, DATA_CORRECTED
  6111 00002333 A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  6112 00002335 7502                <1> 	jnz	short CKST_EXIT
  6113                              <1> 	;mov	ah, 0
  6114 00002337 30E4                <1> 	xor	ah, ah ; 0
  6115                              <1> CKST_EXIT:
  6116 00002339 8825[BB610000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  6117 0000233F 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  6118 00002342 7402                <1> 	je	short CKST_EX1
  6119                              <1> 	;cmp	ah, 0
  6120 00002344 20E4                <1> 	and	ah, ah
  6121                              <1> CKST_EX1:
  6122 00002346 C3                  <1> 	retn
  6123                              <1> 
  6124                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6125                              <1> 
  6126                              <1> ;----------------------------------------
  6127                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  6128                              <1> ;----------------------------------------
  6129                              <1> CHECK_ER:
  6130                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  6131 00002347 668B15[425C0000]    <1> 	mov	dx, [HF_PORT]		;
  6132 0000234E FEC2                <1> 	inc	dl
  6133 00002350 EC                  <1> 	in	al, dx
  6134                              <1> 	; 10/07/2022
  6135                              <1> 	;mov	[HF_ERROR], al
  6136                              <1> 	;push	ebx	; 21/02/2015
  6137 00002351 29C9                <1> 	sub	ecx, ecx
  6138                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  6139 00002353 B108                <1> 	mov	cl, 8
  6140                              <1> CK1:	
  6141 00002355 D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  6142 00002357 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  6143 00002359 E2FA                <1> 	loop	CK1			; KEEP TRYING
  6144                              <1> CK2:
  6145                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  6146                              <1> 	;add	ebx, ecx		; ERROR CODE
  6147 0000235B 81C1[385C0000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  6148                              <1> 
  6149                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  6150                              <1> 	;;mov	ah, [bx]
  6151                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  6152 00002361 8A21                <1> 	mov	ah, [ecx]	
  6153                              <1> CKEX:
  6154 00002363 8825[BB610000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  6155                              <1> 	; 10/07/2022
  6156                              <1> 	;pop	ebx
  6157                              <1> 	;;cmp	ah, 0
  6158                              <1> 	;and	ah, ah
  6159 00002369 C3                  <1> 	retn
  6160                              <1> 
  6161                              <1> ;--------------------------------------------------------
  6162                              <1> ; CHECK_DMA						:
  6163                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  6164                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  6165                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  6166                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  6167                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  6168                              <1> ;  -ERROR OTHERWISE					:
  6169                              <1> ;--------------------------------------------------------
  6170                              <1> 
  6171                              <1> 	; 11/07/2022
  6172                              <1> 	; (not needed for hard disks and 32 bit OS)
  6173                              <1> 	;
  6174                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6175                              <1> ;CHECK_DMA:
  6176                              <1> ;	;;push	ax			; SAVE REGISTERS
  6177                              <1> ;	;; 24/12/2021
  6178                              <1> ;	;;push	eax
  6179                              <1> ;	;mov	ax, 8000h		; AH = MAX # SECTORS
  6180                              <1> ;					; AL = MAX OFFSET
  6181                              <1> ;	; 10/07/2022
  6182                              <1> ;	;test	byte [CMD_BLOCK+6], ECC_MODE
  6183                              <1> ;	;jz	short CKD1
  6184                              <1> ;	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  6185                              <1> ;CKD1:	
  6186                              <1> ;	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  6187                              <1> ;	;ja	short CKDOK		; IT WILL FIT
  6188                              <1> ;	;jb	short CKDERR		; TOO MANY
  6189                              <1> ;	
  6190                              <1> ;	cmp	byte [CMD_BLOCK+1], 80h
  6191                              <1> ;	jb	short CKDOK
  6192                              <1> ;	ja	short CKDERR
  6193                              <1> ;	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  6194                              <1> ;	;jb	short CKDERR		; ERROR
  6195                              <1> ;CKD2:
  6196                              <1> ;	or	bl, bl
  6197                              <1> ;	jz	short CKDR
  6198                              <1> ;	
  6199                              <1> ;;CKDOK:	
  6200                              <1> ;	;clc				; CLEAR CARRY
  6201                              <1> ;	;;pop	ax
  6202                              <1> ;	;; 24/12/2021
  6203                              <1> ;	;pop	eax
  6204                              <1> ;	;retn				; NORMAL RETURN
  6205                              <1> ;CKDERR: 
  6206                              <1> ;	stc				; INDICATE ERROR
  6207                              <1> ;	mov	byte [DISK_STATUS1], DMA_BOUNDARY
  6208                              <1> ;	;;pop	ax
  6209                              <1> ;	;; 24/12/2021
  6210                              <1> ;	;pop	eax	
  6211                              <1> ;	retn
  6212                              <1> ;
  6213                              <1> ;	; 10/07/2022
  6214                              <1> ;CKDOK:
  6215                              <1> ;	clc
  6216                              <1> ;CKDR:
  6217                              <1> ;	retn
  6218                              <1> 
  6219                              <1> ;----------------------------------------
  6220                              <1> ;	SET UP EBX-> DISK PARMS	        :
  6221                              <1> ;----------------------------------------
  6222                              <1> 					
  6223                              <1> ; INPUT -> DL = 0 based drive number
  6224                              <1> ; OUTPUT -> EBX = disk parameter table address
  6225                              <1> 
  6226                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6227                              <1> 
  6228                              <1> GET_VEC:
  6229                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  6230                              <1> 	;mov	es, ax
  6231                              <1> 	;test	dl, 1
  6232                              <1> 	;jz	short GV_0
  6233                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  6234                              <1> ;	jmp	short GV_EXIT
  6235                              <1> ;GV_0:
  6236                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  6237                              <1> ;
  6238 0000236A 31DB                <1> 	xor	ebx, ebx
  6239 0000236C 88D3                <1> 	mov	bl, dl
  6240                              <1> 	;02/01/2015
  6241                              <1> 	;xor	bh, bh
  6242                              <1> 	;shl	bl, 1			; port address offset
  6243                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  6244                              <1> 	;shl	bl, 1			; dpt pointer offset
  6245 0000236E C0E302              <1> 	shl	bl, 2
  6246                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  6247 00002371 81C3[C0610000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  6248                              <1> 	;push	word [bx+2]		; dpt segment
  6249                              <1> 	;pop	es
  6250                              <1> 	;mov	bx, [bx]		; dpt offset
  6251 00002377 8B1B                <1> 	mov	ebx, [ebx]		
  6252                              <1> ;GV_EXIT:
  6253 00002379 C3                  <1> 	retn
  6254                              <1> 
  6255                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6256                              <1> hdc1_int: ; 21/02/2015
  6257                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  6258                              <1> ;								:
  6259                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6260                              <1> ;								:
  6261                              <1> ;----------------------------------------------------------------
  6262                              <1> 
  6263                              <1> ; 22/12/2014
  6264                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  6265                              <1> ;	 '11/15/85'
  6266                              <1> ; AWARD BIOS 1999 (D1A0622) 
  6267                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  6268                              <1> 
  6269                              <1> ;int_76h:
  6270                              <1> HD_INT:
  6271                              <1> 	;push	ax
  6272                              <1> 	; 24/12/2021
  6273 0000237A 50                  <1> 	push	eax
  6274 0000237B 1E                  <1> 	push	ds
  6275                              <1> 	;CALL	DDS
  6276                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6277 0000237C 66B81000            <1> 	mov	ax, KDATA
  6278 00002380 8ED8                <1> 	mov 	ds, ax
  6279                              <1> 	;
  6280                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  6281                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  6282 00002382 C605[B6610000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  6283                              <1> 	;
  6284                              <1> 	;push	dx
  6285                              <1> 	; 24/12/2021
  6286 00002389 52                  <1> 	push	edx
  6287 0000238A 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  6288                              <1> 					; Clear Controller
  6289                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  6290 0000238E EC                  <1> 	in	al, dx			;
  6291                              <1> 	;pop	dx
  6292                              <1> 	; 24/12/2021
  6293 0000238F 5A                  <1> 	pop	edx
  6294                              <1> 	NEWIODELAY
  2196 00002390 E6EB                <2>  out 0EBh,al
  6295                              <1> 	;
  6296 00002392 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  6297 00002394 E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  6298                              <1> 	;JMP	$+2			; WAIT
  6299                              <1> 	NEWIODELAY
  2196 00002396 E6EB                <2>  out 0EBh,al
  6300 00002398 E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  6301 0000239A 1F                  <1> 	pop	ds
  6302                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  6303                              <1> 	;mov	ax, 9100h		; DEVICE POST
  6304                              <1> 	;int	15h			; INTERRUPT
  6305                              <1> irq15_iret: ; 25/02/2015
  6306                              <1> 	;pop	ax
  6307                              <1> 	; 24/12/2021
  6308 0000239B 58                  <1> 	pop	eax
  6309 0000239C CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  6310                              <1> 
  6311                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6312                              <1> hdc2_int: ; 21/02/2015
  6313                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  6314                              <1> ;								:
  6315                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6316                              <1> ;								:
  6317                              <1> ;----------------------------------------------------------------
  6318                              <1> 
  6319                              <1> ;int_77h:
  6320                              <1> HD1_INT:
  6321                              <1> 	;push	ax
  6322                              <1> 	; 24/12/2021
  6323 0000239D 50                  <1> 	push	eax
  6324                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  6325                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  6326 0000239E B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  6327 000023A0 E6A0                <1> 	out	0A0h, al
  6328 000023A2 EB00                <1>         jmp short $+2
  6329 000023A4 EB00                <1> 	jmp short $+2
  6330 000023A6 E4A0                <1> 	in	al, 0A0h
  6331 000023A8 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  6332 000023AA 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  6333                              <1> 	;
  6334 000023AC 1E                  <1> 	push	ds
  6335                              <1> 	;CALL	DDS
  6336                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6337 000023AD 66B81000            <1> 	mov	ax, KDATA
  6338 000023B1 8ED8                <1> 	mov 	ds, ax
  6339                              <1> 	;
  6340                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  6341                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  6342 000023B3 800D[B6610000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  6343                              <1> 	;
  6344                              <1> 	;push	dx
  6345                              <1> 	; 24/12/2021
  6346 000023BA 52                  <1> 	push	edx
  6347 000023BB 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6348                              <1> 					; Clear Controller (Award BIOS 1999)
  6349 000023BF EBCD                <1> 	jmp	short Clear_IRQ1415
  6350                              <1> 
  6351                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6352                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6353                              <1> 
  6354                              <1> ;////////////////////////////////////////////////////////////////////
  6355                              <1> ;; END OF DISK I/O SYTEM ///
  2111                                  %include 'memory.inc'  ; 09/03/2015
  2112                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2113                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.6) - MEMORY.INC
  2114                              <1> ; Last Modification: 17/07/2022
  2115                              <1> ;
  2116                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2117                              <1> 
  2118                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2119                              <1> 
  2120                              <1> ;;04/11/2014 (unix386.s)	
  2121                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2122                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2123                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2124                              <1> ;;
  2125                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2126                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2127                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2128                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2129                              <1> 
  2130                              <1> ; 27/04/2015
  2131                              <1> ; 09/03/2015
  2132                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2133                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2134                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2135                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2136                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2137                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2138                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2139                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2140                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2141                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2142                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2143                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2144                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2145                              <1> SWP_DISK_READ_ERR 	   equ 40
  2146                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2147                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2148                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2149                              <1> SWP_DISK_WRITE_ERR         equ 44
  2150                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2151                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2152                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2153                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2154                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2155                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2156                              <1> 					; (Indicates that the page is not allocated
  2157                              <1> 					; for the process, it is a shared or system
  2158                              <1>                                         ; page, it must not be deallocated!)
  2159                              <1> ; 14/12/2020
  2160                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2161                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2162                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2163                              <1> 				; (Out of memory allocation table)	
  2164                              <1> ;
  2165                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2166                              <1> ;;
  2167                              <1> ;; 10/10/2014
  2168                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2169                              <1> ;;
  2170                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2171                              <1> ;;	(virtual address = physical address)
  2172                              <1> ;; KERNEL PAGE TABLES:
  2173                              <1> ;;	Kernel page directory and all page tables are
  2174                              <1> ;;	on memory as initialized, as equal to physical memory
  2175                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2176                              <1> ;;
  2177                              <1> ;;	what for: User pages may be swapped out, when accessing
  2178                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2179                              <1> ;;	kernel would have to swap it in! But it is also may be
  2180                              <1> ;;	in use by a user process. (In system/kernel mode
  2181                              <1> ;;	kernel can access all memory pages even if they are
  2182                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2183                              <1> ;;	cause conflicts.) 
  2184                              <1> ;;	
  2185                              <1> ;;	As result of these conditions,
  2186                              <1> ;;	all kernel pages must be initialized as equal to 
  2187                              <1> ;;	physical layout for preventing page faults. 
  2188                              <1> ;;	Also, calling "allocate page" procedure after
  2189                              <1> ;;	a page fault can cause another page fault (double fault)
  2190                              <1> ;;	if all kernel page tables would not be initialized.
  2191                              <1> ;;
  2192                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2193                              <1> ;;	memory allocation table. (double word aligned)
  2194                              <1> ;;
  2195                              <1> ;;	[next_page] = first/next free space to be searched
  2196                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2197                              <1> ;;
  2198                              <1> ;;	[last_page] = End of memory (users space), as offset
  2199                              <1> ;;	to memory allocation table. (double word aligned)
  2200                              <1> ;;
  2201                              <1> ;; USER PAGE TABLES:
  2202                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2203                              <1> ;;		'ready only' marked copies of the 
  2204                              <1> ;;		parent process's page table entries (for
  2205                              <1> ;;		same physical memory).
  2206                              <1> ;;		(A page will be copied to a new page after
  2207                              <1> ;;		 if it causes R/W page fault.)
  2208                              <1> ;;
  2209                              <1> ;;	Every user process has own (different)
  2210                              <1> ;;	page directory and page tables.	
  2211                              <1> ;;
  2212                              <1> ;;	Code starts at virtual address 0, always.
  2213                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2214                              <1> ;;	(Programs can be written/developed as simple
  2215                              <1> ;;	 flat memory programs.)
  2216                              <1> ;;
  2217                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2218                              <1> ;;	Memory page will be allocated by kernel only 
  2219                              <1> ;;		(in kernel/system mode only).
  2220                              <1> ;;	* After a
  2221                              <1> ;;	  - 'not present' page fault
  2222                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2223                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2224                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2225                              <1> ;;	  request by running process.
  2226                              <1> ;;	* While creating a process, allocating a new buffer,
  2227                              <1> ;;	  new page tables etc.
  2228                              <1> ;;
  2229                              <1> ;;	At first,
  2230                              <1> ;;	- 'allocate page' procedure will be called;
  2231                              <1> ;,	   if it will return with a valid (>0) physical address
  2232                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2233                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2234                              <1> ;;	- 'allocate page' will be called for allocating page
  2235                              <1> ;;	   directory, page table and running space (data/code).
  2236                              <1> ;;	- every successful 'allocate page' call will decrease
  2237                              <1> ;;	  'free_pages' count (pointer).
  2238                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2239                              <1> ;;	  if 'free_pages' points to a ZERO.
  2240                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2241                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2242                              <1> ;;	  error except errors caused by attribute conflicts.
  2243                              <1> ;;	 (swapper functions)	 
  2244                              <1> ;;					
  2245                              <1> ;;	At second,
  2246                              <1> ;;	- page directory entry will be updated then page table
  2247                              <1> ;;	  entry will be updated.		
  2248                              <1> ;;
  2249                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2250                              <1> ;;	- M.A.T. has a size according to available memory as
  2251                              <1> ;;	  follows:
  2252                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2253                              <1> ;;		  - a bit with value of 0 means allocated page
  2254                              <1> ;;		  - a bit with value of 1 means a free page
  2255                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2256                              <1> ;;	  depending on M.A.T.
  2257                              <1> ;;		(NOTE: Free page count will not be checked
  2258                              <1> ;;		again -on M.A.T.- after initialization. 
  2259                              <1> ;;		Kernel will trust on initial count.)
  2260                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2261                              <1> ;;	  and it will be increased by deallocation procedures.
  2262                              <1> ;;	
  2263                              <1> ;;	- Available memory will be calculated during
  2264                              <1> ;;	  the kernel's initialization stage (in real mode).
  2265                              <1> ;;	  Memory allocation table and kernel page tables 
  2266                              <1> ;;	  will be formatted/sized as result of available
  2267                              <1> ;;	  memory calculation before paging is enabled.
  2268                              <1> ;;
  2269                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2270                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2271                              <1> ;;	- Memory allocation for kernel page directory size 
  2272                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2273                              <1> ;;	  for page tables)
  2274                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2275                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2276                              <1> ;;	- User (available) space will be started 
  2277                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2278                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2279                              <1> ;;	  memory allocation table and kernel's page directory
  2280                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2281                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2282                              <1> ;; 	  for buffers.
  2283                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2284                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2285                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2286                              <1> ;;
  2287                              <1> ;; For 1GB Available Memory:
  2288                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2289                              <1> ;;	- Memory allocation for kernel page directory size 
  2290                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2291                              <1> ;;	  for page tables)
  2292                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2293                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2294                              <1> ;;	- User (available) space will be started 
  2295                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2296                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2297                              <1> ;;	  memory allocation table and kernel's page directory
  2298                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2299                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2300                              <1> ;; 	  for buffers.
  2301                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2302                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2303                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2304                              <1> ;;
  2305                              <1> ;;
  2306                              <1> 
  2307                              <1> ;;************************************************************************************
  2308                              <1> ;; 
  2309                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2310                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2311                              <1> 
  2312                              <1> ;; Main factor: "sys fork" system call 
  2313                              <1> ;;	
  2314                              <1> ;; 		FORK
  2315                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2316                              <1> ;;  writable pages ---->|
  2317                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2318                              <1> ;; 
  2319                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2320                              <1> ;; 
  2321                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2322                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2323                              <1> ;;       -while R/W bit is 0-. 
  2324                              <1> ;; 
  2325                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2326                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2327                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2328                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2329                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2330                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2331                              <1> ;; 
  2332                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2333                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2334                              <1> ;;   Parent's PTE attributes are not changed.
  2335                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2336                              <1> ;;    destroy/mix previous fork result).
  2337                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2338                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2339                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2340                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2341                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2342                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2343                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2344                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2345                              <1> ;; 
  2346                              <1> ;; !? WHAT FOR (duplication after duplication):
  2347                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2348                              <1> ;; program/executable code continues from specified location as child process, 
  2349                              <1> ;; returns back previous code location as parent process, every child after 
  2350                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2351                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2352                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2353                              <1> ;; was copied to child's process segment (all of code and data) according to
  2354                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2355                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2356                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2357                              <1> ;; (complete running image of parent process) to the child process; 
  2358                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2359                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2360                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2361                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2362                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2363                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2364                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2365                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2366                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2367                              <1> ;; for sharing same read only pages between parent and child processes.
  2368                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2369                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2370                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2371                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2372                              <1> ;; -deallocation problem-.
  2373                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2374                              <1> ;; 
  2375                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2376                              <1> ;; # Page fault handler will do those:
  2377                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2378                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2379                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2380                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2381                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2382                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2383                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2384                              <1> ;;     to child process.)	
  2385                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2386                              <1> ;; # Page fault handler will do those:
  2387                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2388                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2389                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2390                              <1> ;;     address or not. 
  2391                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2392                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2393                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2394                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2395                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2396                              <1> ;; 
  2397                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2398                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2399                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2400                              <1> ;;       duplication method details, it is not possible multiple child processes
  2401                              <1> ;;       were using same page with duplicated PTEs.
  2402                              <1> ;; 
  2403                              <1> ;;************************************************************************************   
  2404                              <1> 
  2405                              <1> ;; 08/10/2014
  2406                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2407                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2408                              <1> 
  2409                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2410                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2411                              <1> ;; (25/08/2014, Revision: 5057) file 
  2412                              <1> ;; by KolibriOS Team (2004-2012)
  2413                              <1> 
  2414                              <1> allocate_page:
  2415                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2416                              <1> 	; 01/07/2015
  2417                              <1> 	; 05/05/2015
  2418                              <1> 	; 30/04/2015
  2419                              <1> 	; 16/10/2014
  2420                              <1> 	; 08/10/2014
  2421                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2422                              <1> 	;
  2423                              <1> 	; INPUT -> none
  2424                              <1> 	;
  2425                              <1> 	; OUTPUT ->
  2426                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2427                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2428                              <1> 	;
  2429                              <1> 	;	CF = 1 and EAX = 0 
  2430                              <1> 	; 		   if there is not a free page to be allocated	
  2431                              <1> 	;
  2432                              <1> 	; Modified Registers -> none (except EAX)
  2433                              <1> 	;
  2434 000023C1 A1[30610000]        <1> 	mov	eax, [free_pages]
  2435 000023C6 21C0                <1> 	and	eax, eax
  2436 000023C8 7438                <1> 	jz	short out_of_memory
  2437                              <1> 	;
  2438 000023CA 53                  <1> 	push	ebx
  2439 000023CB 51                  <1> 	push	ecx
  2440                              <1> 	;
  2441 000023CC BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2442 000023D1 89D9                <1> 	mov	ecx, ebx
  2443                              <1>  				     ; NOTE: 32 (first_page) is initial
  2444                              <1> 				     ; value of [next_page].
  2445                              <1> 				     ; It points to the first available
  2446                              <1> 				     ; page block for users (ring 3) ...	
  2447                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2448                              <1> 				     ; (at the of the first 4 MB)		
  2449 000023D3 031D[34610000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2450                              <1> 				 ; next_free_page >> 5
  2451 000023D9 030D[38610000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2452                              <1> 				 ; (total_pages - 1) >> 5
  2453                              <1> al_p_scan:
  2454 000023DF 39CB                <1> 	cmp	ebx, ecx
  2455 000023E1 770A                <1> 	ja	short al_p_notfound
  2456                              <1> 	;
  2457                              <1> 	; 01/07/2015
  2458                              <1> 	; AMD64 Architecture Programmers Manual
  2459                              <1> 	; Volume 3:
  2460                              <1> 	; General-Purpose and System Instructions
  2461                              <1> 	;
  2462                              <1> 	; BSF - Bit Scan Forward
  2463                              <1> 	;
  2464                              <1> 	;   Searches the value in a register or a memory location
  2465                              <1> 	;   (second operand) for the least-significant set bit. 
  2466                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2467                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2468                              <1> 	;   register (first operand). If the second operand contains 0, 
  2469                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2470                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2471                              <1> 	;   of the searched value
  2472                              <1> 	;
  2473 000023E3 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2474                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2475                              <1> 			   ; loads the destination with an index to
  2476                              <1> 			   ; first set bit. (0 -> 31) 
  2477                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2478 000023E6 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2479                              <1> 			 ;
  2480                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2481                              <1> 			 ;	  with value of 1 means 
  2482                              <1> 			 ;	  the corresponding page is free 
  2483                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2484 000023E8 83C304              <1> 	add	ebx, 4
  2485                              <1> 			 ; We return back for searching next page block
  2486                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2487                              <1> 			 ;	 we always will find at least 1 free page here.
  2488 000023EB EBF2                <1>         jmp     short al_p_scan
  2489                              <1> 	;
  2490                              <1> al_p_notfound:
  2491 000023ED 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2492 000023F3 890D[34610000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2493                              <1> 				 ; (deallocate_page procedure will change it)
  2494 000023F9 31C0                <1> 	xor	eax, eax
  2495 000023FB A3[30610000]        <1> 	mov	[free_pages], eax ; 0
  2496 00002400 59                  <1> 	pop	ecx
  2497 00002401 5B                  <1> 	pop	ebx
  2498                              <1> 	;
  2499                              <1> ; 24/12/2021
  2500                              <1> ; ('swap_out' procedure call is disabled)
  2501                              <1> 
  2502                              <1> out_of_memory:
  2503                              <1> ;	call	swap_out
  2504                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2505                              <1> ;	;
  2506                              <1> ;	sub 	eax, eax ; 0
  2507 00002402 F9                  <1> 	stc
  2508 00002403 C3                  <1> 	retn
  2509                              <1> 
  2510                              <1> al_p_found:
  2511 00002404 89D9                <1> 	mov	ecx, ebx
  2512 00002406 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2513 0000240C 890D[34610000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2514                              <1> 				 ; address/offset (to the next)
  2515 00002412 FF0D[30610000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2516                              <1> 	;
  2517 00002418 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2518                              <1> 				 ; is copied into the Carry Flag and then cleared
  2519                              <1> 				 ; in the destination.
  2520                              <1> 				 ;
  2521                              <1> 				 ; Reset the bit which is corresponding to the 
  2522                              <1> 				 ; (just) allocated page.
  2523                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2524 0000241B C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2525 0000241E 01C8                <1> 	add	eax, ecx	 ; = page number
  2526 00002420 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2527                              <1> 	; EAX = physical address of memory page
  2528                              <1> 	;
  2529                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2530                              <1> 	;       according to this EAX value...
  2531 00002423 59                  <1> 	pop	ecx
  2532 00002424 5B                  <1> 	pop	ebx
  2533                              <1> al_p_ok:
  2534 00002425 C3                  <1> 	retn
  2535                              <1> 
  2536                              <1> make_page_dir:
  2537                              <1> 	; 18/04/2015
  2538                              <1> 	; 12/04/2015
  2539                              <1> 	; 23/10/2014
  2540                              <1> 	; 16/10/2014
  2541                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2542                              <1> 	;
  2543                              <1> 	; INPUT ->
  2544                              <1> 	;	none
  2545                              <1> 	; OUTPUT ->
  2546                              <1> 	;	(EAX = 0)
  2547                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2548                              <1> 	;	cf = 0 ->
  2549                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2550                              <1> 	;		  process/user.
  2551                              <1> 	;
  2552                              <1> 	; Modified Registers -> EAX
  2553                              <1> 	;
  2554 00002426 E896FFFFFF          <1> 	call	allocate_page
  2555 0000242B 7216                <1> 	jc	short mkpd_error
  2556                              <1> 	;
  2557 0000242D A3[45650000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2558                              <1> 				  ; (Physical address)
  2559                              <1> clear_page:
  2560                              <1> 	; 18/04/2015
  2561                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2562                              <1> 	;
  2563                              <1> 	; INPUT ->
  2564                              <1> 	;	EAX = physical address of the page
  2565                              <1> 	; OUTPUT ->
  2566                              <1> 	;	all bytes of the page will be cleared
  2567                              <1> 	;
  2568                              <1> 	; Modified Registers -> none
  2569                              <1> 	;
  2570 00002432 57                  <1> 	push	edi
  2571 00002433 51                  <1> 	push	ecx
  2572 00002434 50                  <1> 	push	eax
  2573 00002435 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2574 0000243A 89C7                <1> 	mov	edi, eax
  2575 0000243C 31C0                <1> 	xor	eax, eax
  2576 0000243E F3AB                <1> 	rep	stosd
  2577 00002440 58                  <1> 	pop	eax
  2578 00002441 59                  <1> 	pop	ecx
  2579 00002442 5F                  <1> 	pop	edi
  2580                              <1> mkpd_error:
  2581                              <1> mkpt_error:
  2582 00002443 C3                  <1> 	retn
  2583                              <1> 
  2584                              <1> make_page_table:
  2585                              <1> 	; 23/06/2015
  2586                              <1> 	; 18/04/2015
  2587                              <1> 	; 12/04/2015
  2588                              <1> 	; 16/10/2014
  2589                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2590                              <1> 	;
  2591                              <1> 	; INPUT ->
  2592                              <1> 	;	EBX = virtual (linear) address
  2593                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2594                              <1> 	;	      (higher 20 bits must be ZERO)
  2595                              <1> 	;	      (bit 0 must be 1)	 
  2596                              <1> 	;	u.pgdir = page directory (physical) address
  2597                              <1> 	; OUTPUT ->
  2598                              <1> 	;	EDX = Page directory entry address
  2599                              <1> 	;	EAX = Page table address
  2600                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2601                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2602                              <1> 	;
  2603                              <1> 	; Modified Registers -> EAX, EDX
  2604                              <1> 	;
  2605 00002444 E878FFFFFF          <1> 	call	allocate_page
  2606 00002449 72F8                <1> 	jc	short mkpt_error
  2607 0000244B E811000000          <1> 	call	set_pde	
  2608 00002450 EBE0                <1> 	jmp	short clear_page
  2609                              <1> 
  2610                              <1> make_page:
  2611                              <1> 	; 24/07/2015
  2612                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2613                              <1> 	;
  2614                              <1> 	; INPUT ->
  2615                              <1> 	;	EBX = virtual (linear) address
  2616                              <1> 	;	ECX = page attributes (lower 12 bits)
  2617                              <1> 	;	      (higher 20 bits must be ZERO)
  2618                              <1> 	;	      (bit 0 must be 1)	 
  2619                              <1> 	;	u.pgdir = page directory (physical) address
  2620                              <1> 	; OUTPUT ->
  2621                              <1> 	;	EBX = Virtual address
  2622                              <1> 	;	(EDX = PTE value)
  2623                              <1> 	;	EAX = Physical address
  2624                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2625                              <1> 	;
  2626                              <1> 	; Modified Registers -> EAX, EDX
  2627                              <1> 	;
  2628 00002452 E86AFFFFFF          <1> 	call	allocate_page
  2629 00002457 7207                <1> 	jc	short mkp_err
  2630 00002459 E821000000          <1> 	call	set_pte	
  2631 0000245E 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2632                              <1> mkp_err:
  2633 00002460 C3                  <1> 	retn
  2634                              <1> 
  2635                              <1> set_pde:	; Set page directory entry (PDE)
  2636                              <1> 	; 20/07/2015
  2637                              <1> 	; 18/04/2015
  2638                              <1> 	; 12/04/2015
  2639                              <1> 	; 23/10/2014
  2640                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2641                              <1> 	;
  2642                              <1> 	; INPUT ->
  2643                              <1> 	;	EAX = physical address
  2644                              <1> 	;	      (use present value if EAX = 0)
  2645                              <1> 	;	EBX = virtual (linear) address
  2646                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2647                              <1> 	;	      (higher 20 bits must be ZERO)
  2648                              <1> 	;	      (bit 0 must be 1)	 
  2649                              <1> 	;	u.pgdir = page directory (physical) address
  2650                              <1> 	; OUTPUT ->
  2651                              <1> 	;	EDX = PDE address
  2652                              <1> 	;	EAX = page table address (physical)
  2653                              <1> 	;	;(CF=1 -> Invalid page address)
  2654                              <1> 	;
  2655                              <1> 	; Modified Registers -> EDX
  2656                              <1> 	;
  2657 00002461 89DA                <1> 	mov	edx, ebx
  2658 00002463 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2659 00002466 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2660 00002469 0315[45650000]      <1> 	add	edx, [u.pgdir]
  2661                              <1> 	;
  2662 0000246F 21C0                <1> 	and	eax, eax
  2663 00002471 7506                <1> 	jnz	short spde_1
  2664                              <1> 	;
  2665 00002473 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2666                              <1> 	;test	al, 1
  2667                              <1> 	;jz	short spde_2
  2668 00002475 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2669                              <1> spde_1:
  2670                              <1> 	;and	cx, 0FFFh
  2671 00002479 8902                <1> 	mov	[edx], eax
  2672 0000247B 66090A              <1> 	or	[edx], cx
  2673 0000247E C3                  <1> 	retn
  2674                              <1> ;spde_2: ; error
  2675                              <1> ;	stc
  2676                              <1> ;	retn
  2677                              <1> 
  2678                              <1> set_pte:	; Set page table entry (PTE)
  2679                              <1> 	; 24/07/2015
  2680                              <1> 	; 20/07/2015
  2681                              <1> 	; 23/06/2015
  2682                              <1> 	; 18/04/2015
  2683                              <1> 	; 12/04/2015
  2684                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2685                              <1> 	;
  2686                              <1> 	; INPUT ->
  2687                              <1> 	;	EAX = physical page address
  2688                              <1> 	;	      (use present value if EAX = 0)
  2689                              <1> 	;	EBX = virtual (linear) address
  2690                              <1> 	;	ECX = page attributes (lower 12 bits)
  2691                              <1> 	;	      (higher 20 bits must be ZERO)
  2692                              <1> 	;	      (bit 0 must be 1)	 
  2693                              <1> 	;	u.pgdir = page directory (physical) address
  2694                              <1> 	; OUTPUT ->
  2695                              <1> 	;	EAX = physical page address
  2696                              <1> 	;	(EDX = PTE value)
  2697                              <1> 	;	EBX = virtual address
  2698                              <1> 	;
  2699                              <1> 	;	CF = 1 -> error
  2700                              <1> 	;
  2701                              <1> 	; Modified Registers -> EAX, EDX
  2702                              <1> 	;
  2703 0000247F 50                  <1> 	push	eax
  2704 00002480 A1[45650000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2705 00002485 E837000000          <1> 	call 	get_pde
  2706                              <1> 		; EDX = PDE address
  2707                              <1> 		; EAX = PDE value
  2708 0000248A 5A                  <1> 	pop	edx ; physical page address
  2709 0000248B 722A                <1> 	jc	short spte_err ; PDE not present
  2710                              <1> 	;
  2711 0000248D 53                  <1> 	push	ebx ; 24/07/2015
  2712 0000248E 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2713                              <1> 			    ; EDX = PT address (physical)	
  2714 00002492 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2715 00002495 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2716                              <1> 			 ; clear higher 10 bits (PD bits)
  2717 0000249B C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2718 0000249E 01C3                <1> 	add	ebx, eax
  2719                              <1> 	;
  2720 000024A0 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2721 000024A2 A801                <1> 	test	al, 1
  2722 000024A4 740C                <1> 	jz	short spte_0
  2723 000024A6 09D2                <1> 	or	edx, edx
  2724 000024A8 750F                <1> 	jnz	short spte_1
  2725 000024AA 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2726 000024AE 89C2                <1> 	mov	edx, eax
  2727 000024B0 EB09                <1> 	jmp	short spte_2	
  2728                              <1> spte_0:
  2729                              <1> 	; If this PTE contains a swap (disk) address,
  2730                              <1> 	; it can be updated by using 'swap_in' procedure
  2731                              <1> 	; only!
  2732 000024B2 21C0                <1> 	and	eax, eax
  2733 000024B4 7403                <1> 	jz	short spte_1
  2734                              <1> 	; 24/07/2015
  2735                              <1> 	; swapped page ! (on disk)
  2736 000024B6 5B                  <1> 	pop	ebx
  2737                              <1> spte_err:
  2738 000024B7 F9                  <1> 	stc
  2739 000024B8 C3                  <1> 	retn
  2740                              <1> spte_1: 
  2741 000024B9 89D0                <1> 	mov	eax, edx
  2742                              <1> spte_2:
  2743 000024BB 09CA                <1> 	or	edx, ecx
  2744                              <1> 	; 23/06/2015
  2745 000024BD 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2746                              <1> 	; 24/07/2015
  2747 000024BF 5B                  <1> 	pop	ebx
  2748 000024C0 C3                  <1> 	retn
  2749                              <1> 
  2750                              <1> get_pde:	; Get present value of the relevant PDE
  2751                              <1> 	; 20/07/2015
  2752                              <1> 	; 18/04/2015
  2753                              <1> 	; 12/04/2015
  2754                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2755                              <1> 	;
  2756                              <1> 	; INPUT ->
  2757                              <1> 	;	EBX = virtual (linear) address
  2758                              <1> 	;	EAX = page directory (physical) address
  2759                              <1> 	; OUTPUT ->
  2760                              <1> 	;	EDX = Page directory entry address
  2761                              <1> 	;	EAX = Page directory entry value
  2762                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2763                              <1> 	; Modified Registers -> EDX, EAX
  2764                              <1> 	;
  2765 000024C1 89DA                <1> 	mov	edx, ebx
  2766 000024C3 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2767 000024C6 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2768 000024C9 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2769 000024CB 8B02                <1> 	mov	eax, [edx]
  2770 000024CD A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2771 000024CF 751F                <1> 	jnz	short gpte_retn
  2772 000024D1 F9                  <1> 	stc
  2773                              <1> gpde_retn:	
  2774 000024D2 C3                  <1> 	retn
  2775                              <1> 
  2776                              <1> get_pte:
  2777                              <1> 		; Get present value of the relevant PTE
  2778                              <1> 	; 29/07/2015
  2779                              <1> 	; 20/07/2015
  2780                              <1> 	; 18/04/2015
  2781                              <1> 	; 12/04/2015
  2782                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2783                              <1> 	;
  2784                              <1> 	; INPUT ->
  2785                              <1> 	;	EBX = virtual (linear) address
  2786                              <1> 	;	EAX = page directory (physical) address
  2787                              <1> 	; OUTPUT ->
  2788                              <1> 	;	EDX = Page table entry address (if CF=0)
  2789                              <1> 	;	      Page directory entry address (if CF=1)
  2790                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2791                              <1> 	;	EAX = Page table entry value (page address)
  2792                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2793                              <1> 	; Modified Registers -> EAX, EDX
  2794                              <1> 	;
  2795 000024D3 E8E9FFFFFF          <1> 	call 	get_pde
  2796 000024D8 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2797                              <1> 	;jnc	short gpte_1
  2798                              <1> 	;retn
  2799                              <1> ;gpte_1:
  2800 000024DA 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2801 000024DE 89DA                <1> 	mov	edx, ebx
  2802 000024E0 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2803 000024E3 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2804                              <1> 			 ; clear higher 10 bits (PD bits)
  2805 000024E9 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2806 000024EC 01C2                <1> 	add	edx, eax
  2807 000024EE 8B02                <1> 	mov	eax, [edx]
  2808                              <1> gpte_retn:
  2809 000024F0 C3                  <1> 	retn
  2810                              <1> 
  2811                              <1> deallocate_page_dir:
  2812                              <1> 	; 15/09/2015
  2813                              <1> 	; 05/08/2015
  2814                              <1> 	; 30/04/2015
  2815                              <1> 	; 28/04/2015
  2816                              <1> 	; 17/10/2014
  2817                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2818                              <1> 	;
  2819                              <1> 	; INPUT ->
  2820                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2821                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2822                              <1> 	; OUTPUT ->
  2823                              <1> 	;	All of page tables in the page directory
  2824                              <1> 	;	and page dir's itself will be deallocated
  2825                              <1> 	;	except 'read only' duplicated pages (will be converted
  2826                              <1> 	;	to writable pages).
  2827                              <1> 	;
  2828                              <1> 	; Modified Registers -> EAX
  2829                              <1> 	;
  2830                              <1> 	;
  2831 000024F1 56                  <1> 	push	esi
  2832 000024F2 51                  <1> 	push	ecx
  2833 000024F3 50                  <1> 	push	eax
  2834 000024F4 89C6                <1> 	mov	esi, eax 
  2835 000024F6 31C9                <1> 	xor	ecx, ecx
  2836                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2837                              <1> 	; it must not be deallocated
  2838 000024F8 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2839                              <1> dapd_0:
  2840 000024FA AD                  <1> 	lodsd
  2841 000024FB A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2842 000024FD 7409                <1> 	jz	short dapd_1	
  2843 000024FF 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2844 00002503 E812000000          <1> 	call	deallocate_page_table			
  2845                              <1> dapd_1:
  2846 00002508 41                  <1> 	inc	ecx ; page directory entry index
  2847 00002509 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2848 0000250F 72E9                <1> 	jb	short dapd_0
  2849                              <1> dapd_2:
  2850 00002511 58                  <1> 	pop	eax
  2851 00002512 E870000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2852 00002517 59                  <1> 	pop	ecx
  2853 00002518 5E                  <1> 	pop	esi
  2854 00002519 C3                  <1> 	retn
  2855                              <1> 
  2856                              <1> deallocate_page_table:
  2857                              <1> 	; 17/07/2022
  2858                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2859                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2860                              <1> 	; 19/09/2015
  2861                              <1> 	; 15/09/2015
  2862                              <1> 	; 05/08/2015
  2863                              <1> 	; 30/04/2015
  2864                              <1> 	; 28/04/2015
  2865                              <1> 	; 24/10/2014
  2866                              <1> 	; 23/10/2014
  2867                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2868                              <1> 	;
  2869                              <1> 	; INPUT ->
  2870                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2871                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2872                              <1> 	;	(ECX = page directory entry index)
  2873                              <1> 	; OUTPUT ->
  2874                              <1> 	;	All of pages in the page table and page table's itself
  2875                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2876                              <1> 	;	(will be converted to writable pages).
  2877                              <1> 	;
  2878                              <1> 	; Modified Registers -> EAX
  2879                              <1> 	;
  2880 0000251A 56                  <1> 	push	esi
  2881 0000251B 57                  <1> 	push	edi
  2882 0000251C 52                  <1> 	push	edx
  2883 0000251D 50                  <1> 	push	eax ; *
  2884 0000251E 89C6                <1> 	mov	esi, eax 
  2885 00002520 31FF                <1> 	xor	edi, edi ; 0
  2886                              <1> dapt_0:
  2887 00002522 AD                  <1> 	lodsd
  2888 00002523 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2889 00002525 7453                <1> 	jz	short dapt_1
  2890                              <1> 	;
  2891 00002527 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2892                              <1> 				  ; (must be 1)
  2893 00002529 753D                <1> 	jnz	short dapt_3
  2894                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2895 0000252B 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2896                              <1> 				   ; as child's page ?
  2897 0000252F 7442                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2898                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2899                              <1> 	; ECX = page directory entry index (0-1023)
  2900 00002531 53                  <1> 	push	ebx
  2901 00002532 51                  <1> 	push	ecx
  2902                              <1> 	;shl	cx, 2 ; *4 
  2903                              <1> 	; 17/07/2022
  2904 00002533 C1E102              <1> 	shl	ecx, 2
  2905 00002536 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2906 00002538 8B0B                <1> 	mov	ecx, [ebx]
  2907 0000253A F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2908 0000253D 7427                <1> 	jz	short dapt_2	; parent process does not use this page
  2909 0000253F 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2910                              <1> 	; EDI = page table entry index (0-1023)
  2911 00002544 89FA                <1> 	mov	edx, edi 
  2912                              <1> 	;shl	dx, 2 ; *4
  2913                              <1> 	; 17/07/2022
  2914 00002546 C1E202              <1> 	shl	edx, 2
  2915 00002549 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2916 0000254B 8B1A                <1> 	mov	ebx, [edx]
  2917 0000254D F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2918 00002550 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2919 00002552 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2920 00002556 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2921 0000255B 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2922 0000255D 7507                <1> 	jne	short dapt_2	; not same page
  2923                              <1> 				; deallocate the child's page
  2924 0000255F 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2925 00002562 59                  <1> 	pop	ecx
  2926 00002563 5B                  <1> 	pop	ebx
  2927 00002564 EB0D                <1> 	jmp	short dapt_4
  2928                              <1> 
  2929                              <1> ; 24/12/2021
  2930                              <1> ; ('dapt_1' is disabled)
  2931                              <1> ;
  2932                              <1> ;dapt_1:
  2933                              <1> ;	or	eax, eax	; swapped page ?
  2934                              <1> ;	jz	short dapt_5	; no
  2935                              <1> ;				; yes
  2936                              <1> ;	shr	eax, 1
  2937                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2938                              <1> ;				  ; on the swap disk (or in file)
  2939                              <1> ;	jmp	short dapt_5
  2940                              <1> dapt_2:
  2941 00002566 59                  <1> 	pop	ecx
  2942 00002567 5B                  <1> 	pop	ebx
  2943                              <1> dapt_3:	
  2944                              <1> 	; 12/07/2016
  2945 00002568 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2946 0000256C 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2947                              <1> 	;
  2948                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2949 0000256E E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2950                              <1> dapt_4:
  2951 00002573 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2952                              <1> dapt_1:	; 24/12/2021
  2953                              <1> dapt_5:
  2954 0000257A 47                  <1> 	inc	edi ; page table entry index
  2955 0000257B 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2956 00002581 729F                <1> 	jb	short dapt_0
  2957                              <1> 	;
  2958 00002583 58                  <1> 	pop	eax ; *
  2959 00002584 5A                  <1> 	pop	edx
  2960 00002585 5F                  <1> 	pop	edi	
  2961 00002586 5E                  <1> 	pop	esi
  2962                              <1> 	;
  2963                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2964                              <1> 	;retn
  2965                              <1> 
  2966                              <1> deallocate_page:
  2967                              <1> 	; 15/09/2015
  2968                              <1> 	; 28/04/2015
  2969                              <1> 	; 10/03/2015
  2970                              <1> 	; 17/10/2014
  2971                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2972                              <1> 	;
  2973                              <1> 	; INPUT -> 
  2974                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2975                              <1> 	; OUTPUT ->
  2976                              <1> 	;	[free_pages] is increased
  2977                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2978                              <1> 	;	CF = 1 if the page is already deallocated
  2979                              <1> 	; 	       (or not allocated) before.  
  2980                              <1> 	;
  2981                              <1> 	; Modified Registers -> EAX
  2982                              <1> 	;
  2983 00002587 53                  <1> 	push	ebx
  2984 00002588 52                  <1> 	push	edx
  2985                              <1> 	;
  2986 00002589 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2987                              <1> 				     ; 12 bits right
  2988                              <1> 				     ; to get page number
  2989 0000258C 89C2                <1> 	mov	edx, eax
  2990                              <1> 	; 15/09/2015
  2991 0000258E C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2992                              <1> 				     ; (1 allocation bit = 1 page)
  2993                              <1> 				     ; (1 allocation bytes = 8 pages)
  2994 00002591 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2995                              <1> 				     ; (to get 32 bit position)			
  2996                              <1> 	;
  2997 00002594 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2998 00002599 01D3                <1> 	add	ebx, edx
  2999 0000259B 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  3000                              <1> 				     ; (allocation bit position)	 
  3001 0000259E 3B15[34610000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  3002                              <1> 				     ; than the address in 'next_page' ?
  3003                              <1> 				     ; (next/first free page value)		
  3004 000025A4 7306                <1> 	jnb	short dap_1	     ; no	
  3005 000025A6 8915[34610000]      <1> 	mov	[next_page], edx     ; yes
  3006                              <1> dap_1:
  3007 000025AC 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  3008                              <1> 				     ; set relevant bit to 1.
  3009                              <1> 				     ; set CF to the previous bit value	
  3010                              <1> 	;cmc			     ; complement carry flag	
  3011                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  3012                              <1> 				     ; if the page is already deallocated
  3013                              <1> 				     ; before.	
  3014 000025AF FF05[30610000]      <1>         inc     dword [free_pages]
  3015                              <1> dap_2:
  3016 000025B5 5A                  <1> 	pop	edx
  3017 000025B6 5B                  <1> 	pop	ebx
  3018 000025B7 C3                  <1> 	retn
  3019                              <1> 
  3020                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3021                              <1> ;;                                                              ;;
  3022                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  3023                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  3024                              <1> ;;                                                              ;;
  3025                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3026                              <1> 
  3027                              <1> ;;$Revision: 5057 $
  3028                              <1> 
  3029                              <1> 
  3030                              <1> ;;align 4
  3031                              <1> ;;proc alloc_page
  3032                              <1> 
  3033                              <1> ;;        pushfd
  3034                              <1> ;;        cli
  3035                              <1> ;;        push    ebx
  3036                              <1> ;;;//-
  3037                              <1> ;;        cmp     [pg_data.pages_free], 1
  3038                              <1> ;;        jle     .out_of_memory
  3039                              <1> ;;;//-
  3040                              <1> ;;
  3041                              <1> ;;        mov     ebx, [page_start]
  3042                              <1> ;;        mov     ecx, [page_end]
  3043                              <1> ;;.l1:
  3044                              <1> ;;        bsf     eax, [ebx];
  3045                              <1> ;;        jnz     .found
  3046                              <1> ;;        add     ebx, 4
  3047                              <1> ;;        cmp     ebx, ecx
  3048                              <1> ;;        jb      .l1
  3049                              <1> ;;        pop     ebx
  3050                              <1> ;;        popfd
  3051                              <1> ;;        xor     eax, eax
  3052                              <1> ;;        ret
  3053                              <1> ;;.found:
  3054                              <1> ;;;//-
  3055                              <1> ;;        dec     [pg_data.pages_free]
  3056                              <1> ;;        jz      .out_of_memory
  3057                              <1> ;;;//-
  3058                              <1> ;;        btr     [ebx], eax
  3059                              <1> ;;        mov     [page_start], ebx
  3060                              <1> ;;        sub     ebx, sys_pgmap
  3061                              <1> ;;        lea     eax, [eax+ebx*8]
  3062                              <1> ;;        shl     eax, 12
  3063                              <1> ;;;//-       dec [pg_data.pages_free]
  3064                              <1> ;;        pop     ebx
  3065                              <1> ;;        popfd
  3066                              <1> ;;        ret
  3067                              <1> ;;;//-
  3068                              <1> ;;.out_of_memory:
  3069                              <1> ;;        mov     [pg_data.pages_free], 1
  3070                              <1> ;;        xor     eax, eax
  3071                              <1> ;;        pop     ebx
  3072                              <1> ;;        popfd
  3073                              <1> ;;        ret
  3074                              <1> ;;;//-
  3075                              <1> ;;endp
  3076                              <1> 
  3077                              <1> duplicate_page_dir:
  3078                              <1> 	; 21/09/2015
  3079                              <1> 	; 31/08/2015
  3080                              <1> 	; 20/07/2015
  3081                              <1> 	; 28/04/2015
  3082                              <1> 	; 27/04/2015
  3083                              <1> 	; 18/04/2015
  3084                              <1> 	; 12/04/2015
  3085                              <1> 	; 18/10/2014
  3086                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3087                              <1> 	;
  3088                              <1> 	; INPUT -> 
  3089                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3090                              <1> 	;		    page directory.
  3091                              <1> 	; OUTPUT ->
  3092                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3093                              <1> 	;	       page directory.
  3094                              <1> 	;	(New page directory with new page table entries.)
  3095                              <1> 	;	(New page tables with read only copies of the parent's
  3096                              <1> 	;	pages.)
  3097                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3098                              <1> 	;
  3099                              <1> 	; Modified Registers -> none (except EAX)
  3100                              <1> 	;
  3101 000025B8 E804FEFFFF          <1> 	call	allocate_page
  3102 000025BD 723E                <1> 	jc	short dpd_err
  3103                              <1> 	;
  3104 000025BF 55                  <1> 	push	ebp ; 20/07/2015
  3105 000025C0 56                  <1> 	push	esi
  3106 000025C1 57                  <1> 	push	edi
  3107 000025C2 53                  <1> 	push	ebx
  3108 000025C3 51                  <1> 	push	ecx
  3109 000025C4 8B35[45650000]      <1> 	mov	esi, [u.pgdir]
  3110 000025CA 89C7                <1> 	mov	edi, eax
  3111 000025CC 50                  <1> 	push	eax ; save child's page directory address
  3112                              <1> 	; 31/08/2015
  3113                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3114                              <1> 	; (use same system space for all user page tables) 
  3115 000025CD A5                  <1> 	movsd
  3116 000025CE BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3117 000025D3 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3118                              <1> dpd_0:	
  3119 000025D8 AD                  <1> 	lodsd
  3120                              <1> 	;or	eax, eax
  3121                              <1>         ;jnz     short dpd_1
  3122 000025D9 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3123 000025DB 7508                <1> 	jnz	short dpd_1
  3124                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3125 000025DD 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3126 000025E3 EB0F                <1> 	jmp	short dpd_2
  3127                              <1> dpd_1:	
  3128 000025E5 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3129 000025E9 89C3                <1> 	mov	ebx, eax
  3130                              <1> 	; EBX = Parent's page table address
  3131 000025EB E81F000000          <1> 	call	duplicate_page_table
  3132 000025F0 720C                <1> 	jc	short dpd_p_err
  3133                              <1> 	; EAX = Child's page table address
  3134 000025F2 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3135                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3136                              <1> 			 ; (present, writable, user)
  3137                              <1> dpd_2:
  3138 000025F4 AB                  <1> 	stosd
  3139 000025F5 E2E1                <1> 	loop	dpd_0
  3140                              <1> 	;
  3141 000025F7 58                  <1> 	pop	eax  ; restore child's page directory address
  3142                              <1> dpd_3:
  3143 000025F8 59                  <1> 	pop	ecx
  3144 000025F9 5B                  <1> 	pop	ebx
  3145 000025FA 5F                  <1> 	pop	edi
  3146 000025FB 5E                  <1> 	pop	esi
  3147 000025FC 5D                  <1> 	pop	ebp ; 20/07/2015
  3148                              <1> dpd_err:
  3149 000025FD C3                  <1> 	retn
  3150                              <1> dpd_p_err:
  3151                              <1> 	; release the allocated pages missing (recover free space)
  3152 000025FE 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3153 000025FF 8B1D[45650000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3154 00002605 E8E7FEFFFF          <1> 	call 	deallocate_page_dir
  3155 0000260A 29C0                <1> 	sub	eax, eax ; 0
  3156 0000260C F9                  <1> 	stc
  3157 0000260D EBE9                <1> 	jmp	short dpd_3	
  3158                              <1> 
  3159                              <1> duplicate_page_table:
  3160                              <1> 	; 31/12/2021
  3161                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3162                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3163                              <1> 	; 21/09/2015
  3164                              <1> 	; 20/07/2015
  3165                              <1> 	; 05/05/2015
  3166                              <1> 	; 28/04/2015
  3167                              <1> 	; 27/04/2015
  3168                              <1> 	; 18/04/2015
  3169                              <1> 	; 18/10/2014
  3170                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3171                              <1> 	;
  3172                              <1> 	; INPUT -> 
  3173                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3174                              <1> 	;       20/02/2017		 
  3175                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3176                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3177                              <1> 	; OUTPUT ->
  3178                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3179                              <1> 	;	      (with 'read only' attribute of page table entries)
  3180                              <1> 	;	20/02/2017
  3181                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3182                              <1> 	;	
  3183                              <1> 	;	CF = 1 -> error 
  3184                              <1> 	;
  3185                              <1> 	; Modified Registers -> EBP (except EAX)
  3186                              <1> 	;
  3187 0000260F E8ADFDFFFF          <1> 	call	allocate_page
  3188 00002614 725B                <1> 	jc	short dpt_err
  3189                              <1> 	;
  3190 00002616 50                  <1> 	push	eax ; *
  3191 00002617 56                  <1> 	push	esi
  3192 00002618 57                  <1> 	push	edi
  3193 00002619 52                  <1> 	push	edx
  3194 0000261A 51                  <1> 	push	ecx
  3195                              <1> 	;
  3196 0000261B 89DE                <1> 	mov	esi, ebx
  3197 0000261D 89C7                <1> 	mov	edi, eax
  3198 0000261F 89C2                <1> 	mov	edx, eax
  3199 00002621 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3200                              <1> dpt_0:
  3201 00002627 AD                  <1> 	lodsd
  3202 00002628 21C0                <1> 	and	eax, eax
  3203 0000262A 7435                <1> 	jz	short dpt_3
  3204 0000262C A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3205                              <1> 	; 24/12/2021
  3206 0000262E 7503                <1> 	jnz	short dpt_1
  3207                              <1> 	;jz	short dpt_p_err
  3208                              <1> 	; 31/12/2021
  3209 00002630 F9                  <1> 	stc
  3210 00002631 EB39                <1> 	jmp	short dpt_p_err
  3211                              <1> 
  3212                              <1> ; 24/12/2021
  3213                              <1> ; ('reload_page' procedure call is disabled)
  3214                              <1> ;
  3215                              <1> ;	; 20/07/2015
  3216                              <1> ;	; ebp = virtual (linear) address of the memory page
  3217                              <1> ;	call	reload_page ; 28/04/2015
  3218                              <1> ;	jc	short dpt_p_err
  3219                              <1> dpt_1:
  3220                              <1> 	; 21/09/2015
  3221 00002633 89C1                <1> 	mov	ecx, eax
  3222 00002635 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3223 00002639 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3224 0000263C 751A                <1> 	jnz	short dpt_2
  3225                              <1> 	; Read only (parent) page
  3226                              <1> 	; 	- there is a third process which uses this page -
  3227                              <1> 	; Allocate a new page for the child process
  3228 0000263E E87EFDFFFF          <1> 	call	allocate_page
  3229 00002643 7227                <1> 	jc	short dpt_p_err
  3230 00002645 57                  <1> 	push	edi
  3231 00002646 56                  <1> 	push	esi
  3232 00002647 89CE                <1> 	mov	esi, ecx
  3233 00002649 89C7                <1> 	mov	edi, eax
  3234 0000264B B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3235 00002650 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3236 00002652 5E                  <1> 	pop	esi
  3237 00002653 5F                  <1> 	pop	edi
  3238                              <1> 	;
  3239                              <1> 
  3240                              <1> ; 24/12/2021
  3241                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3242                              <1> ; 
  3243                              <1> ;	push	ebx
  3244                              <1> ;	push	eax
  3245                              <1> ;	; 20/07/2015
  3246                              <1> ;	mov	ebx, ebp
  3247                              <1> ;	; ebx = virtual (linear) address of the memory page
  3248                              <1> ;	call	add_to_swap_queue
  3249                              <1> ;	pop	eax
  3250                              <1> ;	pop	ebx
  3251                              <1> 
  3252                              <1> 	; 21/09/2015
  3253 00002654 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3254                              <1> 		; user + writable + present page
  3255 00002656 EB09                <1> 	jmp	short dpt_3
  3256                              <1> dpt_2:
  3257                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3258 00002658 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3259                              <1> 		    ; (read only page!)
  3260 0000265A 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3261 0000265D 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3262                              <1> dpt_3:
  3263 00002661 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3264                              <1> 	;
  3265 00002662 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3266                              <1> 	;
  3267 00002668 39D7                <1> 	cmp	edi, edx
  3268 0000266A 72BB                <1> 	jb	short dpt_0
  3269                              <1> dpt_p_err:
  3270 0000266C 59                  <1> 	pop	ecx
  3271 0000266D 5A                  <1> 	pop	edx
  3272 0000266E 5F                  <1> 	pop	edi
  3273 0000266F 5E                  <1> 	pop	esi
  3274 00002670 58                  <1> 	pop	eax ; *
  3275                              <1> dpt_err:
  3276 00002671 C3                  <1> 	retn
  3277                              <1> 
  3278                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3279                              <1> 	; 31/12/2021
  3280                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3281                              <1> 	; 21/09/2015
  3282                              <1> 	; 19/09/2015
  3283                              <1> 	; 17/09/2015
  3284                              <1> 	; 28/08/2015
  3285                              <1> 	; 20/07/2015
  3286                              <1> 	; 28/06/2015
  3287                              <1> 	; 03/05/2015
  3288                              <1> 	; 30/04/2015
  3289                              <1> 	; 18/04/2015
  3290                              <1> 	; 12/04/2015
  3291                              <1> 	; 30/10/2014
  3292                              <1> 	; 11/09/2014
  3293                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3294                              <1> 	;
  3295                              <1> 	; Note: This is not an interrupt/exception handler.
  3296                              <1> 	;	This is a 'page fault remedy' subroutine 
  3297                              <1> 	;	which will be called by standard/uniform
  3298                              <1> 	;	exception handler.
  3299                              <1> 	;
  3300                              <1> 	; INPUT -> 
  3301                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3302                              <1> 	;
  3303                              <1> 	;	cr2 = the virtual (linear) address 
  3304                              <1> 	;	      which has caused to page fault (19/09/2015)
  3305                              <1> 	;
  3306                              <1> 	; OUTPUT ->
  3307                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3308                              <1> 	;	EAX = 0 -> no error
  3309                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3310                              <1> 	;
  3311                              <1> 	; Modified Registers -> none (except EAX)
  3312                              <1> 	;	
  3313                              <1>         ;
  3314                              <1>         ; ERROR CODE:
  3315                              <1> 	;	 31  .....	4   3	2   1	0
  3316                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3317                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3318                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3319                              <1> 	;
  3320                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3321                              <1>     	;		a page-protection violation. When not set,
  3322                              <1> 	;		it was caused by a non-present page.
  3323                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3324                              <1> 	;		a page write. When not set, it was caused
  3325                              <1> 	;		by a page read.
  3326                              <1> 	; U : USER    -	When set, the page fault was caused 
  3327                              <1> 	;		while CPL = 3. 
  3328                              <1> 	;		This does not necessarily mean that
  3329                              <1> 	;		the page fault was a privilege violation.
  3330                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3331                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3332                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3333                              <1> 	;     FETCH	an instruction fetch
  3334                              <1> 	;
  3335                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3336                              <1> 	;  31               22                  12 11                    0
  3337                              <1> 	; +-------------------+-------------------+-----------------------+
  3338                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3339                              <1>        	; +-------------------+-------------------+-----------------------+
  3340                              <1> 	;
  3341                              <1> 
  3342                              <1> 	;; CR3 REGISTER (Control Register 3)
  3343                              <1> 	;  31                                   12             5 4 3 2   0
  3344                              <1> 	; +---------------------------------------+-------------+---+-----+
  3345                              <1>       	; |                                       |  		|P|P|     |
  3346                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3347                              <1>       	; |                                       | 		|D|T|     |
  3348                              <1>    	; +---------------------------------------+-------------+---+-----+
  3349                              <1> 	;
  3350                              <1> 	;	PWT    - WRITE THROUGH
  3351                              <1> 	;	PCD    - CACHE DISABLE		
  3352                              <1> 	;
  3353                              <1> 	;
  3354                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3355                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3356                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3357                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3358                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3359                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3360                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3361                              <1> 	;
  3362                              <1>         ;       P      - PRESENT
  3363                              <1>         ;       R/W    - READ/WRITE
  3364                              <1>         ;       U/S    - USER/SUPERVISOR
  3365                              <1> 	;	PWT    - WRITE THROUGH
  3366                              <1> 	;	PCD    - CACHE DISABLE	
  3367                              <1> 	;	A      - ACCESSED	
  3368                              <1>         ;       D      - DIRTY (IGNORED)
  3369                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3370                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3371                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3372                              <1> 	;
  3373                              <1> 	;
  3374                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3375                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3376                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3377                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3378                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3379                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3380                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3381                              <1> 	;
  3382                              <1>         ;       P      - PRESENT
  3383                              <1>         ;       R/W    - READ/WRITE
  3384                              <1>         ;       U/S    - USER/SUPERVISOR
  3385                              <1> 	;	PWT    - WRITE THROUGH
  3386                              <1> 	;	PCD    - CACHE DISABLE	
  3387                              <1> 	;	A      - ACCESSED	
  3388                              <1>         ;       D      - DIRTY
  3389                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3390                              <1> 	;	G      - GLOBAL	 
  3391                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3392                              <1> 	;
  3393                              <1> 	;
  3394                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3395                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3396                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3397                              <1>       	; |                                       |     | | | | | | |U|R| |
  3398                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3399                              <1>       	; |                                       |     | | | | | | |S|W| |
  3400                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3401                              <1> 	;
  3402                              <1>         ;       P      - PRESENT
  3403                              <1>         ;       R/W    - READ/WRITE
  3404                              <1>         ;       U/S    - USER/SUPERVISOR
  3405                              <1>         ;       D      - DIRTY
  3406                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3407                              <1> 	;
  3408                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3409                              <1> 	;
  3410                              <1> 	;
  3411                              <1> 	;; Invalid Page Table Entry
  3412                              <1> 	; 31                                                           1 0
  3413                              <1>       	; +-------------------------------------------------------------+-+
  3414                              <1>       	; |                                                             | |
  3415                              <1>       	; |                          AVAILABLE                          |0|
  3416                              <1>       	; |                                                             | |
  3417                              <1>       	; +-------------------------------------------------------------+-+
  3418                              <1> 	;
  3419                              <1> 
  3420 00002672 53                  <1> 	push	ebx
  3421 00002673 52                  <1> 	push	edx
  3422 00002674 51                  <1> 	push	ecx
  3423                              <1> 	;
  3424                              <1> 	; 21/09/2015 (debugging)
  3425 00002675 FF05[55650000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3426 0000267B FF05[DC610000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3427                              <1> 	; 28/06/2015
  3428                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3429 00002681 8A15[D4610000]      <1> 	mov	dl, [error_code]
  3430                              <1> 	;
  3431 00002687 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3432                              <1> 			; sign
  3433 0000268A 7425                <1> 	jz	short pfh_alloc_np
  3434                              <1> 	; 
  3435                              <1> 	; If it is not a 'write on read only page' type page fault
  3436                              <1> 	; major page fault error with minor reason must be returned without 
  3437                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3438                              <1> 	; after return here!
  3439                              <1> 	; Page fault will be remedied, by copying page contents
  3440                              <1> 	; to newly allocated page with write permission;
  3441                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3442                              <1> 	; used for working with minimum possible memory usage. 
  3443                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3444                              <1> 	; process with 'read only' flag. If the child process attempts to
  3445                              <1> 	; write on these read only pages, page fault will be directed here
  3446                              <1> 	; for allocating a new page with same data/content. 
  3447                              <1> 	;
  3448                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3449                              <1> 	; will not force to separate CODE and DATA space 
  3450                              <1> 	; in a process/program... 
  3451                              <1> 	; CODE segment/section may contain DATA!
  3452                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3453                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3454                              <1> 	;	
  3455 0000268C F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3456                              <1> 			; sign
  3457 0000268F 7418                <1>         jz      pfh_p_err
  3458                              <1> 	; 31/08/2015
  3459 00002691 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3460                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3461 00002694 7413                <1>         jz	short pfh_pv_err
  3462                              <1> 	;
  3463                              <1> 	; make a new page and copy the parent's page content
  3464                              <1> 	; as the child's new page content
  3465                              <1> 	;
  3466 00002696 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3467                              <1> 			 ; which has caused to page fault
  3468 00002699 E87C000000          <1> 	call 	copy_page
  3469 0000269E 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3470                              <1> 	;
  3471 000026A0 EB72                <1>         jmp     pfh_cpp_ok
  3472                              <1> 
  3473                              <1> 	; 31/12/2021 (short jump)
  3474                              <1> pfh_im_err:
  3475 000026A2 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3476                              <1> 			; Major (Primary) Error: Page Fault
  3477                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3478 000026A7 EB6D                <1> 	jmp	short pfh_err_retn
  3479                              <1> 
  3480                              <1> 	; 31/12/2021
  3481                              <1> pfh_p_err: ; 09/03/2015
  3482                              <1> pfh_pv_err:
  3483                              <1> 	; Page fault was caused by a protection-violation
  3484 000026A9 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3485                              <1> 			; Major (Primary) Error: Page Fault
  3486                              <1> 			; Minor (Secondary) Error: Protection violation !
  3487 000026AE F9                  <1> 	stc
  3488 000026AF EB65                <1> 	jmp	short pfh_err_retn
  3489                              <1> 	
  3490                              <1> pfh_alloc_np:
  3491 000026B1 E80BFDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3492 000026B6 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3493                              <1> pfh_chk_cpl:
  3494                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3495                              <1> 		; (Lower 12 bits are ZERO, because 
  3496                              <1> 		;	the address is on a page boundary)
  3497 000026B8 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3498 000026BB 7505                <1> 	jnz	short pfh_um
  3499                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3500 000026BD 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3501                              <1> 			 ; of the current/active page directory
  3502                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3503                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3504 000026C0 EB06                <1> 	jmp	short pfh_get_pde
  3505                              <1> 	;
  3506                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3507 000026C2 8B1D[45650000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3508                              <1> 			; Physical address of the USER's page directory
  3509                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3510                              <1> pfh_get_pde:
  3511 000026C8 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3512 000026CB 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3513                              <1> 			 ; which has been caused to page fault
  3514                              <1> 			 ;
  3515 000026CE C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3516 000026D1 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3517                              <1> 	;
  3518 000026D4 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3519 000026D6 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3520 000026D8 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3521 000026DB 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3522                              <1> 			  	  ; set/validate page directory entry
  3523 000026DD 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3524 000026E2 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3525 000026E4 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3526 000026E6 EB16                <1> 	jmp	short pfh_get_pte
  3527                              <1> pfh_set_pde:
  3528                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3529                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3530                              <1> 	;
  3531 000026E8 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3532 000026EA 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3533 000026EC 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3534 000026EE 89C3                <1> 	mov	ebx, eax
  3535 000026F0 E8CCFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3536 000026F5 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3537                              <1> pfh_spde_1:
  3538                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3539 000026F7 89C1                <1> 	mov	ecx, eax
  3540 000026F9 E834FDFFFF          <1> 	call	clear_page ; Clear page content
  3541                              <1> pfh_get_pte:
  3542 000026FE 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3543                              <1> 			 ; which has been caused to page fault
  3544 00002701 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3545 00002703 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3546                              <1> 			 ; higher 20 bits of the page fault address 
  3547 00002706 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3548 0000270B C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3549 0000270E 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3550                              <1> ; 24/12/2021
  3551                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3552                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3553                              <1> ; 24/12/2021
  3554                              <1> ; ('swap_in' procedure call has been disabled)
  3555                              <1> ;
  3556                              <1> ;	and	eax, eax
  3557                              <1> ;	jz	short pfh_gpte_1
  3558                              <1> ;	; 20/07/2015
  3559                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3560                              <1> ;	push	ebp ; 20/07/2015
  3561                              <1> ;	mov	ebp, cr2
  3562                              <1> ;		; ECX = physical address of the page table entry
  3563                              <1> ;		; EBX = Memory page address (physical!)
  3564                              <1> ;		; EAX = Swap disk (offset) address
  3565                              <1> ;		; EBP = virtual address (page fault address)
  3566                              <1> ;	call	swap_in
  3567                              <1> ;	pop	ebp
  3568                              <1> ;	jc      short pfh_err_retn
  3569                              <1> ;	xchg	ecx, ebx
  3570                              <1> ;		; EBX = physical address of the page table entry
  3571                              <1> ;		; ECX = new page
  3572                              <1> pfh_gpte_1:
  3573 00002710 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3574 00002712 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3575                              <1> pfh_cpp_ok:
  3576                              <1> ; 24/12/2021
  3577                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3578                              <1> ;
  3579                              <1> ;	; 20/07/2015
  3580                              <1> ;	mov	ebx, cr2
  3581                              <1> ;	call 	add_to_swap_queue
  3582                              <1> 	;
  3583                              <1> 	; The new PTE (which contains the new page) will be added to 
  3584                              <1> 	; the swap queue, here. 
  3585                              <1> 	; (Later, if memory will become insufficient, 
  3586                              <1> 	; one page will be swapped out which is at the head of 
  3587                              <1> 	; the swap queue by using FIFO and access check methods.)
  3588                              <1> 	;
  3589 00002714 31C0                <1> 	xor	eax, eax  ; 0
  3590                              <1> 	;
  3591                              <1> pfh_err_retn:
  3592 00002716 59                  <1> 	pop	ecx
  3593 00002717 5A                  <1> 	pop	edx
  3594 00002718 5B                  <1> 	pop	ebx
  3595 00002719 C3                  <1> 	retn 
  3596                              <1> 	
  3597                              <1> copy_page:
  3598                              <1> 	; 17/07/2022
  3599                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3600                              <1> 	; 16/04/2021
  3601                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3602                              <1> 	; 22/09/2015
  3603                              <1> 	; 21/09/2015
  3604                              <1> 	; 19/09/2015
  3605                              <1> 	; 07/09/2015
  3606                              <1> 	; 31/08/2015
  3607                              <1> 	; 20/07/2015
  3608                              <1> 	; 05/05/2015
  3609                              <1> 	; 03/05/2015
  3610                              <1> 	; 18/04/2015
  3611                              <1> 	; 12/04/2015
  3612                              <1> 	; 30/10/2014
  3613                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3614                              <1> 	;
  3615                              <1> 	; INPUT -> 
  3616                              <1> 	;	EBX = Virtual (linear) address of source page
  3617                              <1> 	;	     (Page fault address)
  3618                              <1> 	; OUTPUT ->
  3619                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3620                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3621                              <1> 	;	EAX = 0 (CF = 1) 
  3622                              <1> 	;		if there is not a free page to be allocated
  3623                              <1> 	;	(page content of the source page will be copied
  3624                              <1> 	;	onto the target/new page) 	
  3625                              <1> 	;
  3626                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3627                              <1> 	;
  3628                              <1> 
  3629                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3630                              <1> 	; INPUT: 
  3631                              <1> 	;	EBX = Virtual (linear) address of source page
  3632                              <1> 	;	     (Page fault address)
  3633                              <1> 	; OUTPUT:
  3634                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3635                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3636                              <1> 	;	EAX = 0 (CF = 1) 
  3637                              <1> 	;		if there is not a free page to be allocated
  3638                              <1> 	;	(page content of the source page will be copied
  3639                              <1> 	;	onto the target/new page) 	
  3640                              <1> 	;
  3641                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3642                              <1> 	
  3643 0000271A 56                  <1> 	push	esi ; *
  3644 0000271B 57                  <1> 	push	edi ; **
  3645                              <1> 	; 16/04/2021
  3646                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3647                              <1> 	;push	ebx ; ***
  3648                              <1> 	;push	ecx ; ****
  3649 0000271C 31F6                <1> 	xor 	esi, esi
  3650 0000271E C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3651 00002721 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3652 00002723 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3653 00002726 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3654 00002729 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3655 0000272B 031D[45650000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3656 00002731 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3657 00002733 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3658 00002737 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3659 00002739 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3660                              <1> 	;shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3661                              <1> 	; 17/07/2022
  3662 0000273F C1E302              <1> 	shl	ebx, 2
  3663 00002742 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3664                              <1> 	; 07/09/2015
  3665 00002744 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3666                              <1> 				     ; read only page as a child process?)	
  3667 00002749 7509                <1> 	jnz	short cpp_0 ; yes
  3668 0000274B 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3669 0000274D 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3670 00002752 EB31                <1> 	jmp	short cpp_1
  3671                              <1> cpp_0:
  3672 00002754 89FE                <1> 	mov	esi, edi
  3673 00002756 0335[49650000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3674 0000275C 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3675 0000275E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3676 00002762 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3677 00002764 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3678                              <1> 	;shl	si, 2	   ; shift 2 bits left to get PTE offset
  3679                              <1> 	; 17/07/2022
  3680 0000276A C1E602              <1> 	shl	esi, 2
  3681 0000276D 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3682 0000276F 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3683                              <1> 	; 21/09/2015
  3684 00002771 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3685 00002773 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3686                              <1> 	;
  3687 00002777 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3688 0000277A 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3689                              <1> 	;
  3690 0000277C 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3691 00002781 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3692 00002783 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3693                              <1> 			    ; Convert child's page to writable page
  3694                              <1> cpp_1:
  3695 00002785 E837FCFFFF          <1> 	call	allocate_page
  3696 0000278A 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3697 0000278C 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3698 0000278E 7405                <1> 	jz	short cpp_2
  3699                              <1> 		; Convert read only page to writable page 
  3700                              <1> 		;(for the parent of the current process)
  3701                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3702                              <1> 	; 22/09/2015
  3703 00002790 890E                <1> 	mov	[esi], ecx
  3704 00002792 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3705                              <1> 				 ; 1+2+4 = 7
  3706                              <1> cpp_2:
  3707 00002795 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3708                              <1> 	; 07/09/2015
  3709 00002797 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3710 00002799 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3711 0000279E F3A5                <1> 	rep	movsd ; 31/08/2015
  3712                              <1> cpp_3:		
  3713 000027A0 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3714 000027A2 8903                <1> 	mov	[ebx], eax ; Update PTE
  3715 000027A4 28C0                <1> 	sub	al, al ; clear attributes
  3716                              <1> cpp_4:
  3717                              <1> 	; 16/04/2021
  3718                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3719                              <1> 	;pop	ecx ; ****
  3720                              <1> 	;pop	ebx ; ***
  3721 000027A6 5F                  <1> 	pop	edi ; **
  3722 000027A7 5E                  <1> 	pop	esi ; *
  3723 000027A8 C3                  <1> 	retn
  3724                              <1> 
  3725                              <1> ;; 28/04/2015
  3726                              <1> ;; 24/10/2014
  3727                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3728                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3729                              <1> ;;
  3730                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3731                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3732                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3733                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3734                              <1> ;;
  3735                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3736                              <1> ;;
  3737                              <1> ;; Method:
  3738                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3739                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3740                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3741                              <1> ;;	When a new page is being allocated, swap queue is updated
  3742                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3743                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3744                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3745                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3746                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3747                              <1> ;;	offset value becomes it's previous offset value - 4.
  3748                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3749                              <1> ;;	the queue/list is not shifted.
  3750                              <1> ;;	After the queue/list shift, newly allocated page is added
  3751                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3752                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3753                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3754                              <1> ;;	
  3755                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3756                              <1> ;;	the first non-accessed, writable page in the list, 
  3757                              <1> ;;	from the head to the tail. The list is shifted to left 
  3758                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3759                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3760                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3761                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3762                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3763                              <1> ;;	procedure will be failed)...
  3764                              <1> ;;
  3765                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3766                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3767                              <1> ;;	(PTE) will be added to the tail of the queue after
  3768                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3769                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3770                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3771                              <1> ;;
  3772                              <1> ;;
  3773                              <1> ;;	
  3774                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3775                              <1> ;;
  3776                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3777                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3778                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3779                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3780                              <1> ;;
  3781                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3782                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3783                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3784                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3785                              <1> ;; 		 (entire swap space must be accessed by using
  3786                              <1> ;;		 31 bit offset address) 
  3787                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3788                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3789                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3790                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3791                              <1> ;;
  3792                              <1> ;; 					
  3793                              <1> ;; Method:
  3794                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3795                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3796                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3797                              <1> ;;	Swapping out is performed by using swap page queue.
  3798                              <1> ;;
  3799                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3800                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3801                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3802                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3803                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3804                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3805                              <1> ;;	calculated by adding offset value to the swap partition's 
  3806                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3807                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3808                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3809                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3810                              <1> ;;	is in a partitioned virtual hard disk.) 
  3811                              <1> ;;
  3812                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3813                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3814                              <1> ;;
  3815                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3816                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3817                              <1> ;;
  3818                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3819                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3820                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3821                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3822                              <1> ;;	it means relevant (respective) block is in use, and, 
  3823                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3824                              <1> ;;      swap disk/file block is free.
  3825                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3826                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3827                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3828                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3829                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3830                              <1> ;;	------------------------------------------------------------
  3831                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3832                              <1> ;;	------------------------------------------------------------
  3833                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3834                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3835                              <1> ;;
  3836                              <1> ;;	..............................................................
  3837                              <1> ;;
  3838                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3839                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3840                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3841                              <1> ;;	position with value of 1 on the table is converted to swap
  3842                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3843                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3844                              <1> ;;	number of physical swap disk or virtual swap disk)
  3845                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3846                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3847                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3848                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3849                              <1> ;;	If disk write procedure returns with error or free count of 
  3850                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3851                              <1> ;;	'insufficient memory error' (cf=1). 
  3852                              <1> ;;
  3853                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3854                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3855                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3856                              <1> ;;	free blocks after a disk write error. It will return to 
  3857                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3858                              <1> ;;
  3859                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3860                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3861                              <1> ;;	address (cf=0). 
  3862                              <1> ;;
  3863                              <1> ;;	..............................................................
  3864                              <1> ;;
  3865                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3866                              <1> ;;	file sectors at specified memory page. Then page allocation
  3867                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3868                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3869                              <1> ;;	to do, except to terminate the process which is the owner of
  3870                              <1> ;;	the swapped page.
  3871                              <1> ;;
  3872                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3873                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3874                              <1> ;;	updates [swpd_first] pointer if it is required.
  3875                              <1> ;;
  3876                              <1> ;;	..............................................................	 
  3877                              <1> ;;
  3878                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3879                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3880                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3881                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3882                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3883                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3884                              <1> ;;
  3885                              <1> 
  3886                              <1> ; 24/12/2021
  3887                              <1> ; ('swap_in' procedure call is disabled)
  3888                              <1> 
  3889                              <1> ;swap_in:
  3890                              <1> 	; 31/08/2015
  3891                              <1> 	; 20/07/2015
  3892                              <1> 	; 28/04/2015
  3893                              <1> 	; 18/04/2015
  3894                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3895                              <1> 	;
  3896                              <1> 	; INPUT -> 
  3897                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3898                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3899                              <1> 	;	EAX = Offset Address for the swapped page on the
  3900                              <1> 	;	      swap disk or in the swap file.
  3901                              <1> 	;
  3902                              <1> 	; OUTPUT ->
  3903                              <1> 	;	EAX = 0 if loading at memory has been successful
  3904                              <1> 	;
  3905                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3906                              <1> 	;		  or sector not present or drive not ready
  3907                              <1> 	;	     EAX = Error code
  3908                              <1> 	;	     [u.error] = EAX 
  3909                              <1> 	;		       = The last error code for the process
  3910                              <1> 	;		         (will be reset after returning to user)	  
  3911                              <1> 	;
  3912                              <1> 	; Modified Registers -> EAX
  3913                              <1> 	;
  3914                              <1> 
  3915                              <1> ;       cmp     dword [swp_drv], 0
  3916                              <1> ;	jna	short swpin_dnp_err
  3917                              <1> ;
  3918                              <1> ;	cmp	eax, [swpd_size]
  3919                              <1> ;	jnb	short swpin_snp_err
  3920                              <1> ;
  3921                              <1> ;	push	esi
  3922                              <1> ;	push	ebx
  3923                              <1> ;	push	ecx
  3924                              <1> ;	mov	esi, [swp_drv]	
  3925                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3926                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3927                              <1> ;		; size different than 512 bytes, logical disk sector
  3928                              <1> ;		; size is 512 bytes and disk reading procedure
  3929                              <1> ;		; will be performed for reading 4096 bytes
  3930                              <1> ;		; (2*2048, 8*512). 
  3931                              <1> ;	; ESI = Logical disk description table address
  3932                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3933                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3934                              <1> ;	; ECX = Sector count ; 8 sectors
  3935                              <1> ;	push	eax
  3936                              <1> ;	call	logical_disk_read
  3937                              <1> ;	pop	eax
  3938                              <1> ;	jnc	short swpin_read_ok
  3939                              <1> ;	;
  3940                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3941                              <1> ;	mov	[u.error], eax
  3942                              <1> ;	jmp	short swpin_retn
  3943                              <1> ;	;
  3944                              <1> ;swpin_read_ok:
  3945                              <1> ;	; EAX = Offset address (logical sector number)
  3946                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3947                              <1> ;	;
  3948                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3949                              <1> ;	; 20/07/2015
  3950                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3951                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3952                              <1> ;	mov	bl, [u.uno] ; current process number
  3953                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3954                              <1> ;	call	swap_queue_shift
  3955                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3956                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3957                              <1> ;	; zf = 1
  3958                              <1> ;swpin_retn:
  3959                              <1> ;	pop	ecx
  3960                              <1> ;	pop	ebx
  3961                              <1> ;	pop	esi
  3962                              <1> ;	retn
  3963                              <1> ;
  3964                              <1> ;swpin_dnp_err:
  3965                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3966                              <1> ;swpin_err_retn:
  3967                              <1> ;	mov	[u.error], eax
  3968                              <1> ;	stc
  3969                              <1> ;	retn
  3970                              <1> ;
  3971                              <1> ;swpin_snp_err:
  3972                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3973                              <1> ;	jmp	short swpin_err_retn
  3974                              <1> 
  3975                              <1> ; 24/12/2021
  3976                              <1> ; ('swap_out' procedure call is disabled)
  3977                              <1> 
  3978                              <1> ;swap_out:
  3979                              <1> 	; 10/06/2016
  3980                              <1> 	; 07/06/2016
  3981                              <1>         ; 23/05/2016
  3982                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3983                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3984                              <1> 	;
  3985                              <1> 	; INPUT -> 
  3986                              <1> 	;	none
  3987                              <1> 	;
  3988                              <1> 	; OUTPUT ->
  3989                              <1> 	;	EAX = Physical page address (which is swapped out
  3990                              <1> 	;	      for allocating a new page)
  3991                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3992                              <1> 	;		  or sector not present or drive not ready
  3993                              <1> 	;	     EAX = Error code
  3994                              <1> 	;	     [u.error] = EAX 
  3995                              <1> 	;		       = The last error code for the process
  3996                              <1> 	;		         (will be reset after returning to user)	  
  3997                              <1> 	;
  3998                              <1> 	; Modified Registers -> none (except EAX)
  3999                              <1> 	;
  4000                              <1> 
  4001                              <1> ;	cmp 	word [swpq_count], 1
  4002                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  4003                              <1> ;
  4004                              <1> ;       ;cmp    dword [swp_drv], 1
  4005                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  4006                              <1> ;
  4007                              <1> ;       cmp     dword [swpd_free], 1
  4008                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  4009                              <1> ;
  4010                              <1> ;	push	ebx ; *
  4011                              <1> ;swpout_1:
  4012                              <1> ;	; 10/06/2016
  4013                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  4014                              <1> ;	call	swap_queue_shift
  4015                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  4016                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  4017                              <1> ;				       ; pointer in the swap queue
  4018                              <1> ;	; EAX = PTE value of the page
  4019                              <1> ;	; EBX = PTE address of the page
  4020                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4021                              <1> ;	;
  4022                              <1> ;	; 07/06/2016
  4023                              <1> ;	; 19/05/2016
  4024                              <1> ;	; check this page is in timer events or not
  4025                              <1> ;	
  4026                              <1> ;swpout_timer_page_0:
  4027                              <1> ;	push	edx ; **
  4028                              <1> ;
  4029                              <1> ;	; 07/06/2016
  4030                              <1> ;	cmp	byte [timer_events], 0 
  4031                              <1> ;	jna	short swpout_2
  4032                              <1> ;	;
  4033                              <1> ;	mov	dl, [timer_events]
  4034                              <1> ;
  4035                              <1> ;	push	ecx ; ***
  4036                              <1> ;	push	ebx ; ****
  4037                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4038                              <1> ;			       ; structures 
  4039                              <1> ;swpout_timer_page_1:
  4040                              <1> ;	mov	cl, [ebx]
  4041                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4042                              <1> ;	jz	short swpout_timer_page_3
  4043                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4044                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4045                              <1> ;				; of the response byte address, to
  4046                              <1> ;				; get beginning of the page address)
  4047                              <1> ;	cmp	eax, ecx
  4048                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4049                              <1> ;	
  4050                              <1> ;	; !same page!
  4051                              <1> ;	;
  4052                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4053                              <1> ;	; This page will be used by the kernel to put timer event
  4054                              <1> ;	; response (signal return) byte at the requested address;
  4055                              <1> ;	; in order to prevent a possible wrong write (while
  4056                              <1> ;	; this page is swapped out) on physical memory,
  4057                              <1> ;	; we must protect this page against to be swapped out!
  4058                              <1> ;	;
  4059                              <1> ;	pop	ebx ; ****
  4060                              <1> ;	pop	ecx ; ***
  4061                              <1> ;	pop	edx ; **
  4062                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4063                              <1> ; 
  4064                              <1> ;swpout_timer_page_2:
  4065                              <1> ;	; 07/06/2016
  4066                              <1> ;	dec	dl
  4067                              <1> ;	jz	short swpout_timer_page_4
  4068                              <1> ;swpout_timer_page_3:
  4069                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4070                              <1> ;	;jnb	short swpout_timer_page_4
  4071                              <1> ;	add	ebx, 16
  4072                              <1> ;	jmp	short swpout_timer_page_1	
  4073                              <1> ;
  4074                              <1> ;swpout_timer_page_4:
  4075                              <1> ;	pop	ebx ; ****
  4076                              <1> ;	pop	ecx ; ***
  4077                              <1> ;swpout_2:
  4078                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4079                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4080                              <1> ;	;
  4081                              <1> ;	call	link_swap_block
  4082                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4083                              <1> ;				       ; because [swpd_free] value
  4084                              <1> ;				       ; was checked at the beginging. 	
  4085                              <1> ;	pop	edx ; **
  4086                              <1> ;	pop	ebx ; *
  4087                              <1> ;	jmp	short swpout_nfspc_err 
  4088                              <1> ;swpout_3:
  4089                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4090                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4091                              <1> ;	;	
  4092                              <1> ;	push	esi ; **
  4093                              <1> ;	push	ecx ; ***
  4094                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4095                              <1> ;	mov	esi, [swp_drv]	
  4096                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4097                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4098                              <1> ;		; size different than 512 bytes, logical disk sector
  4099                              <1> ;		; size is 512 bytes and disk writing procedure
  4100                              <1> ;		; will be performed for writing 4096 bytes
  4101                              <1> ;		; (2*2048, 8*512). 
  4102                              <1> ;	; ESI = Logical disk description table address
  4103                              <1> ;	; EBX = Buffer (Page) address
  4104                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4105                              <1> ;	; ECX = Sector count ; 8 sectors
  4106                              <1> ;	; edx = PTE address
  4107                              <1> ;	call	logical_disk_write
  4108                              <1> ;	; edx = PTE address
  4109                              <1> ;	pop	ecx ; sector address	
  4110                              <1> ;	jnc	short swpout_write_ok
  4111                              <1> ;	;
  4112                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4113                              <1> ;swpout_dw_err:
  4114                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4115                              <1> ;	mov	[u.error], eax
  4116                              <1> ;	jmp	short swpout_retn
  4117                              <1> ;	;
  4118                              <1> ;swpout_write_ok:
  4119                              <1> ;	; EBX = Buffer (page) address
  4120                              <1> ;	; EDX = Page Table Entry address
  4121                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4122                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4123                              <1> ;	mov 	[edx], ecx 
  4124                              <1> ;		; bit 0 = 0 (swapped page)
  4125                              <1> ;	mov	eax, ebx
  4126                              <1> ;swpout_retn:
  4127                              <1> ;	pop	ecx ; ***
  4128                              <1> ;	pop	esi ; **
  4129                              <1> ;	pop	ebx ; *
  4130                              <1> ;	retn
  4131                              <1> ;
  4132                              <1> ;;swpout_dnp_err:
  4133                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4134                              <1> ;;	jmp	short swpout_err_retn
  4135                              <1> ;swpout_nfspc_err:
  4136                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4137                              <1> ;swpout_err_retn:
  4138                              <1> ;	mov	[u.error], eax
  4139                              <1> ;	;stc
  4140                              <1> ;	retn
  4141                              <1> ;swpout_npts_err:
  4142                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4143                              <1> ;	pop	ebx
  4144                              <1> ;	jmp	short swpout_err_retn
  4145                              <1> ;swpout_im_err:
  4146                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4147                              <1> ;	jmp	short swpout_err_retn
  4148                              <1> 
  4149                              <1> ; 24/12/2021
  4150                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4151                              <1> 
  4152                              <1> ;swap_queue_shift:
  4153                              <1> 	; 26/03/2017
  4154                              <1> 	; 10/06/2016
  4155                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4156                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4157                              <1> 	;
  4158                              <1> 	; INPUT ->
  4159                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4160                              <1> 	;	      and process number combination (bit 0 to 11)
  4161                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4162                              <1> 	;	
  4163                              <1> 	; OUTPUT ->
  4164                              <1> 	;	If EBX input > 0 
  4165                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4166                              <1> 	; 	   from the tail to the head, up to entry offset
  4167                              <1> 	; 	   which points to EBX input value or nothing
  4168                              <1> 	;	   to do if EBX value is not found on the queue.
  4169                              <1> 	;	   (The entry -with EBX value- will be removed
  4170                              <1> 	;	   from the queue if it is found.)
  4171                              <1> 	;
  4172                              <1> 	;	   EAX = 0		
  4173                              <1> 	;
  4174                              <1> 	;	If EBX input = 0
  4175                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4176                              <1> 	; 	   from the tail to the head, if the PTE address
  4177                              <1> 	;	   which is pointed in head of the queue is marked
  4178                              <1> 	;	   as "accessed" or it is marked as "non present".
  4179                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4180                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4181                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4182                              <1> 	;	   -without dropping pointer of the PTE from 
  4183                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4184                              <1> 	;	   Pointer in the head will be moved into the tail,
  4185                              <1> 	;	   other PTEs will be shifted on head direction.)
  4186                              <1> 	;
  4187                              <1> 	;	   Swap queue will be shifted up to the first
  4188                              <1> 	;	   'present' or 'non accessed' page will be found
  4189                              <1> 	;	   (as pointed) on the queue head (then it will be
  4190                              <1>         ;          removed/dropped from the queue).
  4191                              <1> 	;
  4192                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4193                              <1> 	;		 (it's pointer -virtual address-) dropped
  4194                              <1> 	;		 (removed) from swap queue.
  4195                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4196                              <1> 	;	         which is (it's pointer -virtual address-)
  4197                              <1> 	;		 dropped (removed) from swap queue.
  4198                              <1> 	;
  4199                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4200                              <1> 	;
  4201                              <1> 	; Modified Registers -> EAX, EBX
  4202                              <1> 	;
  4203                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4204                              <1> ;	and	ax, ax
  4205                              <1> ;	jz	short swpqs_retn
  4206                              <1> ;	push	edi
  4207                              <1> ;	push	esi
  4208                              <1> ;	push	ecx
  4209                              <1> ;	mov	esi, swap_queue
  4210                              <1> ;	mov	ecx, eax
  4211                              <1> ;	or	ebx, ebx
  4212                              <1> ;	jz	short swpqs_7
  4213                              <1> ;swpqs_1:
  4214                              <1> ;	lodsd
  4215                              <1> ;	cmp	eax, ebx
  4216                              <1> ;	je	short swpqs_2
  4217                              <1> ;	loop	swpqs_1
  4218                              <1> ;	; 10/06/2016
  4219                              <1> ;	sub	eax, eax 
  4220                              <1> ;	jmp	short swpqs_6
  4221                              <1> ;swpqs_2:
  4222                              <1> ;	mov	edi, esi
  4223                              <1> ;	sub 	edi, 4
  4224                              <1> ;swpqs_3:
  4225                              <1> ;	dec	word [swpq_count]
  4226                              <1> ;	jz	short swpqs_5
  4227                              <1> ;swpqs_4:
  4228                              <1> ;	dec 	ecx
  4229                              <1> ;	rep	movsd	; shift up (to the head)
  4230                              <1> ;swpqs_5:
  4231                              <1> ;	xor	eax, eax
  4232                              <1> ;	mov	[edi], eax
  4233                              <1> ;swpqs_6:
  4234                              <1> ;	pop	ecx
  4235                              <1> ;	pop	esi
  4236                              <1> ;	pop	edi
  4237                              <1> ;swpqs_retn:
  4238                              <1> ;	retn		
  4239                              <1> ;swpqs_7:
  4240                              <1> ;	mov	edi, esi ; head
  4241                              <1> ;	lodsd
  4242                              <1> ;	; 20/07/2015
  4243                              <1> ;	mov	ebx, eax
  4244                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4245                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4246                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4247                              <1> ;		      ; ax = process number (1 to 4095)
  4248                              <1> ;	cmp	al, [u.uno]
  4249                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4250                              <1> ;	jne	short swpqs_8
  4251                              <1> ;	mov	eax, [u.pgdir]
  4252                              <1> ;	jmp	short swpqs_9
  4253                              <1> ;swpqs_8:
  4254                              <1> ;	; 09/06/2016
  4255                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4256                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4257                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4258                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4259                              <1> ;
  4260                              <1> ;	;shl	ax, 2
  4261                              <1> ;	shl	al, 2
  4262                              <1> ;	mov 	eax, [eax+p.upage-4]
  4263                              <1> ;	or	eax, eax
  4264                              <1> ;	jz	short swpqs_3 ; invalid upage
  4265                              <1> ;	add	eax, u.pgdir - user
  4266                              <1> ;			 ; u.pgdir value for the process
  4267                              <1> ;			 ; is in [eax]
  4268                              <1> ;	mov	eax, [eax]
  4269                              <1> ;	and	eax, eax
  4270                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4271                              <1> ;swpqs_9:
  4272                              <1> ;	push	edx
  4273                              <1> ;	; eax = page directory
  4274                              <1> ;	; ebx = virtual address
  4275                              <1> ;	call	get_pte
  4276                              <1> ;	mov	ebx, edx	; PTE address
  4277                              <1> ;	pop	edx
  4278                              <1> ;	; 10/06/2016
  4279                              <1> ;	jc	short swpqs_13 ; empty PDE
  4280                              <1> ;	; EAX = PTE value
  4281                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4282                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4283                              <1> ;			        ; from the queue (head)
  4284                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4285                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4286                              <1> ;			        ; from the queue (head) 	
  4287                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4288                              <1> ;	;jnz	short swpqs_11  ; present
  4289                              <1> ;			        ; accessed page
  4290                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4291                              <1> ;	jc	short swpqs_11  ; accessed page
  4292                              <1> ;
  4293                              <1> ;	dec	ecx
  4294                              <1> ;	mov	[swpq_count], cx
  4295                              <1> ;       jz      short swpqs_10
  4296                              <1> ;		; esi = head + 4
  4297                              <1> ;		; edi = head
  4298                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4299                              <1> ;swpqs_10:
  4300                              <1> ;	mov	[edi], ecx ; 0
  4301                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4302                              <1> ;
  4303                              <1> ;swpqs_11:
  4304                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4305                              <1> ;	; Rotation (head -> tail)
  4306                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4307                              <1> ;	jz	short swpqs_10
  4308                              <1> ;		; esi = head + 4
  4309                              <1> ;		; edi = head
  4310                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4311                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4312                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4313                              <1> ;
  4314                              <1> ;	mov	cx, [swpq_count]
  4315                              <1> ;
  4316                              <1> ;swpqs_12:
  4317                              <1> ;	mov	esi, swap_queue ; head
  4318                              <1> ;       jmp     swpqs_7
  4319                              <1> ;
  4320                              <1> ;swpqs_13:
  4321                              <1> ;	dec	ecx
  4322                              <1> ;	mov	[swpq_count], cx
  4323                              <1> ;       jz      swpqs_5
  4324                              <1> ;	jmp	short swpqs_12
  4325                              <1> 
  4326                              <1> ; 24/12/2021
  4327                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4328                              <1> 
  4329                              <1> ;add_to_swap_queue:
  4330                              <1> 	; 20/02/2017
  4331                              <1> 	; 20/07/2015
  4332                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4333                              <1> 	;
  4334                              <1> 	; Adds new page to swap queue
  4335                              <1> 	; (page directories and page tables must not be added
  4336                              <1> 	; to swap queue)	
  4337                              <1> 	;
  4338                              <1> 	; INPUT ->
  4339                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4340                              <1> 	;	[u.uno]
  4341                              <1> 	;	20/02/2017
  4342                              <1> 	;	(Linear address = CORE + user's virtual address)
  4343                              <1> 	;
  4344                              <1> 	; OUTPUT ->
  4345                              <1> 	;	EAX = [swpq_count]
  4346                              <1> 	;	      (after the PTE has been added)
  4347                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4348                              <1> 	;	      the PTE could not be added.
  4349                              <1> 	;
  4350                              <1> 	; Modified Registers -> EAX
  4351                              <1> 	;
  4352                              <1> ;	push	ebx
  4353                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4354                              <1> ;	mov	bl, [u.uno] ; current process number
  4355                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4356                              <1> ;				 ; it is already on the queue
  4357                              <1> ;		; then add it to the tail of the queue
  4358                              <1> ;	movzx	eax, word [swpq_count]
  4359                              <1> ;	cmp	ax, 1024
  4360                              <1> ;	jb	short atsq_1
  4361                              <1> ;	sub	ax, ax
  4362                              <1> ;	pop	ebx
  4363                              <1> ;	retn
  4364                              <1> ;atsq_1:
  4365                              <1> ;	push	esi
  4366                              <1> ;	mov	esi, swap_queue
  4367                              <1> ;	and	ax, ax
  4368                              <1> ;	jz	short atsq_2
  4369                              <1> ;	shl	ax, 2	; convert to offset
  4370                              <1> ;	add	esi, eax
  4371                              <1> ;	shr	ax, 2
  4372                              <1> ;atsq_2:
  4373                              <1> ;	inc	ax
  4374                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4375                              <1> ;	mov	[swpq_count], ax
  4376                              <1> ;	pop	esi
  4377                              <1> ;	pop	ebx
  4378                              <1> ;	retn
  4379                              <1> 
  4380                              <1> ; 24/12/2021
  4381                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4382                              <1> 
  4383                              <1> ;unlink_swap_block:
  4384                              <1> 	; 15/09/2015
  4385                              <1> 	; 30/04/2015
  4386                              <1> 	; 18/04/2015
  4387                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4388                              <1> 	;
  4389                              <1> 	; INPUT -> 
  4390                              <1> 	;	EAX = swap disk/file offset address
  4391                              <1> 	;	      (bit 1 to bit 31)
  4392                              <1> 	; OUTPUT ->
  4393                              <1> 	;	[swpd_free] is increased
  4394                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4395                              <1> 	;
  4396                              <1> 	; Modified Registers -> EAX
  4397                              <1> 	;
  4398                              <1> ;	push	ebx
  4399                              <1> ;	push	edx
  4400                              <1> ;	;
  4401                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4402                              <1> ;				     ; 3 bits right
  4403                              <1> ;				     ; to get swap block/page number
  4404                              <1> ;	mov	edx, eax
  4405                              <1> ;	; 15/09/2015
  4406                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4407                              <1> ;				     ; (1 allocation bit = 1 page)
  4408                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4409                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4410                              <1> ;				     ; (to get 32 bit position)			
  4411                              <1> ;	;
  4412                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4413                              <1> ;	add	ebx, edx
  4414                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4415                              <1> ;				     ; (allocation bit position)	 
  4416                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4417                              <1> ;				     ; than the address in 'swpd_next' ?
  4418                              <1> ;				     ; (next/first free block value)		
  4419                              <1> ;	jnb	short uswpbl_1	     ; no	
  4420                              <1> ;	mov	[swpd_next], eax     ; yes	
  4421                              <1> ;uswpbl_1:
  4422                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4423                              <1> ;				     ; set relevant bit to 1.
  4424                              <1> ;				     ; set CF to the previous bit value	
  4425                              <1> ;	cmc			     ; complement carry flag	
  4426                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4427                              <1> ;				     ; if the block is already deallocated
  4428                              <1> ;				     ; before.	
  4429                              <1> ;       inc     dword [swpd_free]
  4430                              <1> ;uswpbl_2:
  4431                              <1> ;	pop	edx
  4432                              <1> ;	pop	ebx
  4433                              <1> ;	retn
  4434                              <1> 
  4435                              <1> ; 24/12/2021
  4436                              <1> ; ('link_swap_block' procedure call is disabled)
  4437                              <1> 
  4438                              <1> ;link_swap_block:
  4439                              <1> 	; 01/07/2015
  4440                              <1> 	; 18/04/2015
  4441                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4442                              <1> 	;
  4443                              <1> 	; INPUT -> none
  4444                              <1> 	;
  4445                              <1> 	; OUTPUT ->
  4446                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4447                              <1> 	;	      in sectors (corresponding 
  4448                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4449                              <1> 	;
  4450                              <1> 	;	CF = 1 and EAX = 0 
  4451                              <1> 	; 		   if there is not a free block to be allocated	
  4452                              <1> 	;
  4453                              <1> 	; Modified Registers -> none (except EAX)
  4454                              <1> 	;
  4455                              <1> 
  4456                              <1> ;	;mov	eax, [swpd_free]
  4457                              <1> ;	;and	eax, eax
  4458                              <1> ;	;jz	short out_of_swpspc
  4459                              <1> ;	;
  4460                              <1> ;	push	ebx
  4461                              <1> ;	push	ecx
  4462                              <1> ;	;
  4463                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4464                              <1> ;	mov	ecx, ebx
  4465                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4466                              <1> ;				 ; next_free_swap_block >> 5
  4467                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4468                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4469                              <1> ;lswbl_scan:
  4470                              <1> ;	cmp	ebx, ecx
  4471                              <1> ;	ja	short lswbl_notfound
  4472                              <1> ;	;
  4473                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4474                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4475                              <1> ;			   ; loads the destination with an index to
  4476                              <1> ;			   ; first set bit. (0 -> 31) 
  4477                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4478                              <1> ;	; 01/07/2015
  4479                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4480                              <1> ;			 ;
  4481                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4482                              <1> ;			 ;	  with value of 1 means 
  4483                              <1> ;			 ;	  the corresponding page is free 
  4484                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4485                              <1> ;	add	ebx, 4
  4486                              <1> ;			 ; We return back for searching next page block
  4487                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4488                              <1> ;			 ;	 we always will find at least 1 free block here.
  4489                              <1> ;	jmp    	short lswbl_scan
  4490                              <1> ;	;
  4491                              <1> ;lswbl_notfound:	
  4492                              <1> ;	sub	ecx, swap_alloc_table
  4493                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4494                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4495                              <1> ;	xor	eax, eax
  4496                              <1> ;	mov	[swpd_free], eax
  4497                              <1> ;	stc
  4498                              <1> ;lswbl_ok:
  4499                              <1> ;	pop	ecx
  4500                              <1> ;	pop	ebx
  4501                              <1> ;	retn
  4502                              <1> ;	;
  4503                              <1> ;;out_of_swpspc:
  4504                              <1> ;;	stc
  4505                              <1> ;;	retn
  4506                              <1> ;
  4507                              <1> ;lswbl_found:
  4508                              <1> ;	mov	ecx, ebx
  4509                              <1> ;	sub	ecx, swap_alloc_table
  4510                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4511                              <1> ;				 ; address/offset (to the next)
  4512                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4513                              <1> ;	;
  4514                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4515                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4516                              <1> ;				 ; in the destination.
  4517                              <1> ;				 ;
  4518                              <1> ;				 ; Reset the bit which is corresponding to the 
  4519                              <1> ;				 ; (just) allocated block.
  4520                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4521                              <1> ;	add	eax, ecx	 ; = block number
  4522                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4523                              <1> ;				 ; 1 block =  8 sectors
  4524                              <1> ;	;
  4525                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4526                              <1> ;	;
  4527                              <1> ;	; NOTE: The relevant page table entry will be updated
  4528                              <1> ;	;       according to this EAX value...
  4529                              <1> ;	;
  4530                              <1> ;	jmp	short lswbl_ok
  4531                              <1> 
  4532                              <1> ; 24/12/2021
  4533                              <1> ; ('logical_disk_read' procedure call is disabled)
  4534                              <1> 
  4535                              <1> ;logical_disk_read:
  4536                              <1> 	; 20/07/2015
  4537                              <1> 	; 09/03/2015 (temporary code here)
  4538                              <1> 	;
  4539                              <1> 	; INPUT ->
  4540                              <1> 	; 	ESI = Logical disk description table address
  4541                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4542                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4543                              <1> 	; 	ECX = Sector count
  4544                              <1> 	;
  4545                              <1> 	;
  4546                              <1> ;	retn
  4547                              <1> 
  4548                              <1> ; 24/12/2021
  4549                              <1> ; ('logical_disk_write' procedure call is disabled)
  4550                              <1> 
  4551                              <1> ;logical_disk_write:
  4552                              <1> 	; 20/07/2015
  4553                              <1> 	; 09/03/2015 (temporary code here)
  4554                              <1> 	;
  4555                              <1> 	; INPUT ->
  4556                              <1> 	; 	ESI = Logical disk description table address
  4557                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4558                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4559                              <1> 	; 	ECX = Sector count
  4560                              <1> 	;
  4561                              <1> ;	retn
  4562                              <1> 
  4563                              <1> get_physical_addr:
  4564                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4565                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4566                              <1> 	; 18/10/2015
  4567                              <1> 	; 29/07/2015
  4568                              <1> 	; 20/07/2015
  4569                              <1> 	; 04/06/2015
  4570                              <1> 	; 20/05/2015
  4571                              <1> 	; 28/04/2015
  4572                              <1> 	; 18/04/2015
  4573                              <1> 	; Get physical address
  4574                              <1> 	;     (allocates a new page for user if it is not present)
  4575                              <1> 	;	
  4576                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4577                              <1> 	; (buffer) address to physical address (of the buffer).)
  4578                              <1> 	; ('sys write', 'sys read' system calls...)
  4579                              <1> 	;
  4580                              <1> 	; INPUT ->
  4581                              <1> 	;	EBX = virtual address
  4582                              <1> 	;	u.pgdir = page directory (physical) address
  4583                              <1> 	;
  4584                              <1> 	; OUTPUT ->
  4585                              <1> 	;	EAX = physical address 
  4586                              <1> 	;	EBX = linear address	
  4587                              <1> 	;	EDX = physical address of the page frame
  4588                              <1> 	;	      (with attribute bits)
  4589                              <1> 	;	ECX = byte count within the page frame
  4590                              <1> 	;
  4591                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4592                              <1> 	;
  4593                              <1> 
  4594                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4595 000027A9 A1[45650000]        <1> 	mov	eax, [u.pgdir]
  4596                              <1> 
  4597                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4598                              <1> 	
  4599 000027AE 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4600                              <1> 	;
  4601                              <1> 	;mov	eax, [u.pgdir]
  4602 000027B4 E81AFDFFFF          <1> 	call	get_pte
  4603                              <1> 		; EDX = Page table entry address (if CF=0)
  4604                              <1> 	        ;       Page directory entry address (if CF=1)
  4605                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4606                              <1> 		; EAX = Page table entry value (page address)
  4607                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4608 000027B9 731C                <1> 	jnc	short gpa_1
  4609                              <1> 	;
  4610 000027BB E801FCFFFF          <1> 	call	allocate_page
  4611 000027C0 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4612                              <1> gpa_0:
  4613 000027C2 E86BFCFFFF          <1> 	call 	clear_page
  4614                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4615 000027C7 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4616                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4617                              <1> 			   ; (user, writable, present page)	
  4618 000027C9 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4619 000027CB A1[45650000]        <1> 	mov	eax, [u.pgdir]	
  4620 000027D0 E8FEFCFFFF          <1> 	call	get_pte
  4621 000027D5 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4622                              <1> gpa_1:
  4623                              <1> 	; EAX = PTE value, EDX = PTE address
  4624 000027D7 A801                <1> 	test 	al, PTE_A_PRESENT
  4625 000027D9 750A                <1> 	jnz	short gpa_3
  4626 000027DB 09C0                <1> 	or	eax, eax
  4627 000027DD 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4628                              <1> 
  4629                              <1> ; 24/12/2021
  4630                              <1> ; ('reload_page' procedure call is disabled)
  4631 000027DF EB2C                <1> 	jmp	short gpa_im_err
  4632                              <1> 
  4633                              <1> 	; 20/07/2015
  4634                              <1> ;	push	ebp
  4635                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4636                              <1> ;	; reload swapped page
  4637                              <1> ;	call	reload_page ; 28/04/2015
  4638                              <1> ;	pop	ebp
  4639                              <1> ;	jc	short gpa_retn
  4640                              <1> gpa_2:
  4641                              <1> ; 24/12/2021
  4642                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4643                              <1> 
  4644                              <1> 	; 20/07/2015
  4645                              <1> 	; 20/05/2015
  4646                              <1> 	; add this page to swap queue
  4647                              <1> ;	push	eax 
  4648                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4649                              <1> ;	call 	add_to_swap_queue
  4650                              <1> ;	pop	eax
  4651                              <1> 		; PTE address in EDX
  4652                              <1> 		; virtual address in EBX
  4653                              <1> 	; EAX = memory page address
  4654 000027E1 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4655                              <1> 				  ; present flag, bit 0 = 1
  4656                              <1> 				  ; user flag, bit 2 = 1	
  4657                              <1> 				  ; writable flag, bit 1 = 1
  4658 000027E3 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4659                              <1> gpa_3:
  4660                              <1> 	; 18/10/2015
  4661 000027E5 89D9                <1> 	mov	ecx, ebx
  4662 000027E7 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4663 000027ED 89C2                <1> 	mov 	edx, eax
  4664 000027EF 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4665 000027F3 01C8                <1> 	add	eax, ecx
  4666 000027F5 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4667 000027F7 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4668 000027FD F8                  <1> 	clc
  4669                              <1> gpa_retn:
  4670 000027FE C3                  <1> 	retn	
  4671                              <1> gpa_4:	
  4672 000027FF E8BDFBFFFF          <1> 	call	allocate_page
  4673 00002804 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4674 00002806 E827FCFFFF          <1> 	call	clear_page
  4675 0000280B EBD4                <1> 	jmp	short gpa_2
  4676                              <1> 
  4677                              <1> gpa_im_err:	
  4678 0000280D B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4679                              <1> 				  ; Major error = 0 (No protection fault)	
  4680 00002812 C3                  <1> 	retn
  4681                              <1> 
  4682                              <1> ; 24/12/2021
  4683                              <1> ; ('reload_page' procedure call is disabled)
  4684                              <1> 
  4685                              <1> ;reload_page:
  4686                              <1> 	; 20/07/2015
  4687                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4688                              <1> 	;
  4689                              <1> 	; Reload (Restore) swapped page at memory
  4690                              <1> 	;
  4691                              <1> 	; INPUT -> 
  4692                              <1> 	;	EBP = Virtual (linear) memory address
  4693                              <1> 	;	EAX = PTE value (swap disk sector address)
  4694                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4695                              <1> 	; OUTPUT ->
  4696                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4697                              <1> 	;
  4698                              <1> 	;	CF = 1 and EAX = error code
  4699                              <1> 	;
  4700                              <1> 	; Modified Registers -> none (except EAX)
  4701                              <1> 	;
  4702                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4703                              <1> ;	push	ebx      ;
  4704                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4705                              <1> ;	call	allocate_page
  4706                              <1> ;	jc	short rlp_im_err
  4707                              <1> ;	xchg 	eax, ebx	
  4708                              <1> ;	; EBX = Physical memory (page) address
  4709                              <1> ;	; EAX = Swap disk (offset) address
  4710                              <1> ;	; EBP = Virtual (linear) memory address
  4711                              <1> ;	call	swap_in
  4712                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4713                              <1> ;	mov	eax, ebx	
  4714                              <1> ;rlp_retn:
  4715                              <1> ;	pop	ebx
  4716                              <1> ;	retn
  4717                              <1> ;	
  4718                              <1> ;rlp_im_err:	
  4719                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4720                              <1> ;				  ; Major error = 0 (No protection fault)	
  4721                              <1> ;	jmp	short rlp_retn
  4722                              <1> ;
  4723                              <1> ;rlp_swp_err:
  4724                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4725                              <1> ;	jmp	short rlp_retn
  4726                              <1> 
  4727                              <1> copy_page_dir:
  4728                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4729                              <1> 	; 19/09/2015
  4730                              <1> 	; temporary - 07/09/2015
  4731                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4732                              <1> 	;
  4733                              <1> 	; INPUT -> 
  4734                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4735                              <1> 	;		    page directory.
  4736                              <1> 	; OUTPUT ->
  4737                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4738                              <1> 	;	       page directory.
  4739                              <1> 	;	(New page directory with new page table entries.)
  4740                              <1> 	;	(New page tables with read only copies of the parent's
  4741                              <1> 	;	pages.)
  4742                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4743                              <1> 	;
  4744                              <1> 	; Modified Registers -> none (except EAX)
  4745                              <1> 	;
  4746 00002813 E8A9FBFFFF          <1> 	call	allocate_page
  4747 00002818 723E                <1> 	jc	short cpd_err
  4748                              <1> 	;
  4749 0000281A 55                  <1> 	push	ebp ; 20/07/2015
  4750 0000281B 56                  <1> 	push	esi
  4751 0000281C 57                  <1> 	push	edi
  4752 0000281D 53                  <1> 	push	ebx
  4753 0000281E 51                  <1> 	push	ecx
  4754 0000281F 8B35[45650000]      <1> 	mov	esi, [u.pgdir]
  4755 00002825 89C7                <1> 	mov	edi, eax
  4756 00002827 50                  <1> 	push	eax ; save child's page directory address
  4757                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4758                              <1> 	; (use same system space for all user page tables) 
  4759 00002828 A5                  <1> 	movsd
  4760 00002829 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4761 0000282E B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4762                              <1> cpd_0:	
  4763 00002833 AD                  <1> 	lodsd
  4764                              <1> 	;or	eax, eax
  4765                              <1>         ;jnz	short cpd_1
  4766 00002834 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4767 00002836 7508                <1> 	jnz	short cpd_1
  4768                              <1>  	; (virtual address at the end of the page table)	
  4769 00002838 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4770 0000283E EB0F                <1> 	jmp	short cpd_2
  4771                              <1> cpd_1:	
  4772 00002840 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4773 00002844 89C3                <1> 	mov	ebx, eax
  4774                              <1> 	; EBX = Parent's page table address
  4775 00002846 E81F000000          <1> 	call	copy_page_table
  4776 0000284B 720C                <1> 	jc	short cpd_p_err
  4777                              <1> 	; EAX = Child's page table address
  4778 0000284D 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4779                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4780                              <1> 			 ; (present, writable, user)
  4781                              <1> cpd_2:
  4782 0000284F AB                  <1> 	stosd
  4783 00002850 E2E1                <1> 	loop	cpd_0
  4784                              <1> 	;
  4785 00002852 58                  <1> 	pop	eax  ; restore child's page directory address
  4786                              <1> cpd_3:
  4787 00002853 59                  <1> 	pop	ecx
  4788 00002854 5B                  <1> 	pop	ebx
  4789 00002855 5F                  <1> 	pop	edi
  4790 00002856 5E                  <1> 	pop	esi
  4791 00002857 5D                  <1> 	pop	ebp
  4792                              <1> cpd_err:
  4793 00002858 C3                  <1> 	retn
  4794                              <1> cpd_p_err:
  4795                              <1> 	; release the allocated pages missing (recover free space)
  4796 00002859 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4797 0000285A 8B1D[45650000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4798 00002860 E88CFCFFFF          <1> 	call 	deallocate_page_dir
  4799 00002865 29C0                <1> 	sub	eax, eax ; 0
  4800 00002867 F9                  <1> 	stc
  4801 00002868 EBE9                <1> 	jmp	short cpd_3	
  4802                              <1> 
  4803                              <1> copy_page_table:
  4804                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4805                              <1> 	; 19/09/2015
  4806                              <1> 	; temporary - 07/09/2015
  4807                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4808                              <1> 	;
  4809                              <1> 	; INPUT -> 
  4810                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4811                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4812                              <1> 	; OUTPUT ->
  4813                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4814                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4815                              <1> 	;	CF = 1 -> error 
  4816                              <1> 	;
  4817                              <1> 	; Modified Registers -> EBP (except EAX)
  4818                              <1> 	;
  4819 0000286A E852FBFFFF          <1> 	call	allocate_page
  4820 0000286F 7244                <1> 	jc	short cpt_err
  4821                              <1> 	;
  4822 00002871 50                  <1> 	push	eax ; *
  4823                              <1> 	;push 	ebx
  4824 00002872 56                  <1> 	push	esi
  4825 00002873 57                  <1> 	push	edi
  4826 00002874 52                  <1> 	push	edx
  4827 00002875 51                  <1> 	push	ecx
  4828                              <1> 	;
  4829 00002876 89DE                <1> 	mov	esi, ebx
  4830 00002878 89C7                <1> 	mov	edi, eax
  4831 0000287A 89C2                <1> 	mov	edx, eax
  4832 0000287C 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4833                              <1> cpt_0:
  4834 00002882 AD                  <1> 	lodsd
  4835 00002883 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4836                              <1> 	;jnz	short cpt_1 (*)
  4837                              <1> 	; 24/12/2021
  4838                              <1> 	;and	eax, eax (*)
  4839 00002885 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4840                              <1> 	
  4841                              <1> ; 24/12/2021
  4842                              <1> ; ('reload_page' procedure call is disabled)
  4843                              <1> ;
  4844                              <1> ;	; ebp = virtual (linear) address of the memory page
  4845                              <1> ;	call	reload_page ; 28/04/2015
  4846                              <1> ;	jc	short cpt_p_err
  4847                              <1> cpt_1:
  4848 00002887 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4849 0000288B 89C1                <1> 	mov	ecx, eax
  4850                              <1> 	; Allocate a new page for the child process
  4851 0000288D E82FFBFFFF          <1> 	call	allocate_page
  4852 00002892 721C                <1> 	jc	short cpt_p_err
  4853 00002894 57                  <1> 	push	edi
  4854 00002895 56                  <1> 	push	esi
  4855 00002896 89CE                <1> 	mov	esi, ecx
  4856 00002898 89C7                <1> 	mov	edi, eax
  4857 0000289A B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4858 0000289F F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4859 000028A1 5E                  <1> 	pop	esi
  4860 000028A2 5F                  <1> 	pop	edi
  4861                              <1> 	; 
  4862                              <1> ; 24/12/2021
  4863                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4864                              <1> ;
  4865                              <1> ;	push	ebx
  4866                              <1> ;	push	eax
  4867                              <1> ;	mov	ebx, ebp
  4868                              <1> ;	; ebx = virtual address of the memory page
  4869                              <1> ;	call	add_to_swap_queue
  4870                              <1> ;	pop	eax
  4871                              <1> ;	pop	ebx
  4872                              <1> 	;
  4873                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4874 000028A3 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4875                              <1> cpt_2:
  4876 000028A5 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4877                              <1> 	;
  4878 000028A6 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4879                              <1> 	;
  4880 000028AC 39D7                <1> 	cmp	edi, edx
  4881 000028AE 72D2                <1> 	jb	short cpt_0
  4882                              <1> cpt_p_err:
  4883 000028B0 59                  <1> 	pop	ecx
  4884 000028B1 5A                  <1> 	pop	edx
  4885 000028B2 5F                  <1> 	pop	edi
  4886 000028B3 5E                  <1> 	pop	esi
  4887                              <1> 	;pop	ebx
  4888 000028B4 58                  <1> 	pop	eax ; *
  4889                              <1> cpt_err:
  4890 000028B5 C3                  <1> 	retn
  4891                              <1> 
  4892                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4893                              <1> 
  4894                              <1> ;; Data:
  4895                              <1> 
  4896                              <1> ; 09/03/2015
  4897                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4898                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4899                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4900                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4901                              <1> ;swpd_next:  dd 0 ; next free page block
  4902                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2112                                  %include 'sysdefs.inc' ; 09/03/2015
  2113                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.6) - SYSDEFS.INC
  2114                              <1> ; Last Modification: 15/07/2022
  2115                              <1> ;
  2116                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2117                              <1> ; (Modified from 
  2118                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2119                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2120                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2121                              <1> ; ----------------------------------------------------------------------------
  2122                              <1> ;
  2123                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2124                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2125                              <1> ; <Bell Laboratories (17/3/1972)>
  2126                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2127                              <1> ;
  2128                              <1> ; ****************************************************************************
  2129                              <1> 
  2130                              <1> nproc 	equ	16  ; number of processes
  2131                              <1> nfiles 	equ	50
  2132                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2133                              <1> ;nbuf	equ	6   ; number of buffers (04/02/2016)
  2134                              <1> nbuf	equ	8   ; 15/07/2022 
  2135                              <1> 
  2136                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2137                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2138                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2139                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2140                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2141                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2142                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2143                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2144                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2145                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2146                              <1> 	; '/core' dump file size = 32768 bytes
  2147                              <1>  
  2148                              <1> ; 08/03/2014 
  2149                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2150                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feature only !
  2151                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2152                              <1> 
  2153                              <1> ; 30/08/2013
  2154                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2155                              <1> 
  2156                              <1> ; 05/02/2014
  2157                              <1> ; process status
  2158                              <1> ;SFREE 	equ 0
  2159                              <1> ;SRUN	equ 1
  2160                              <1> ;SWAIT	equ 2
  2161                              <1> ;SZOMB	equ 3
  2162                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2163                              <1> 
  2164                              <1> ; 09/03/2015
  2165                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2166                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2167                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2168                              <1> 
  2169                              <1> ; 17/09/2015
  2170                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2171                              <1> 
  2172                              <1> ; 21/09/2015 (36) 
  2173                              <1> ; 01/07/2015 (35)
  2174                              <1> ; 14/07/2013 (0-34)
  2175                              <1> ; UNIX v1 system calls
  2176                              <1> _rele 	equ 0
  2177                              <1> _exit 	equ 1
  2178                              <1> _fork 	equ 2
  2179                              <1> _read 	equ 3
  2180                              <1> _write	equ 4
  2181                              <1> _open	equ 5
  2182                              <1> _close 	equ 6
  2183                              <1> _wait 	equ 7
  2184                              <1> _creat 	equ 8
  2185                              <1> _link 	equ 9
  2186                              <1> _unlink	equ 10
  2187                              <1> _exec	equ 11
  2188                              <1> _chdir	equ 12
  2189                              <1> _time 	equ 13
  2190                              <1> _mkdir 	equ 14
  2191                              <1> _chmod	equ 15
  2192                              <1> _chown	equ 16
  2193                              <1> _break	equ 17
  2194                              <1> _stat	equ 18
  2195                              <1> _seek	equ 19
  2196                              <1> _tell 	equ 20
  2197                              <1> _mount	equ 21
  2198                              <1> _umount	equ 22
  2199                              <1> _setuid	equ 23
  2200                              <1> _getuid	equ 24
  2201                              <1> _stime	equ 25
  2202                              <1> _quit	equ 26	
  2203                              <1> _intr	equ 27
  2204                              <1> _fstat	equ 28
  2205                              <1> _emt 	equ 29
  2206                              <1> _mdate 	equ 30
  2207                              <1> _stty 	equ 31
  2208                              <1> _gtty	equ 32
  2209                              <1> _ilgins	equ 33
  2210                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2211                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2212                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2213                              <1> 
  2214                              <1> %macro sys 1-4
  2215                              <1>     ; 13/04/2015
  2216                              <1>     ; Retro UNIX 386 v1 system call.		
  2217                              <1>     mov eax, %1
  2218                              <1>     %if %0 >= 2   
  2219                              <1>         mov ebx, %2
  2220                              <1>         %if %0 >= 3    
  2221                              <1>             mov ecx, %3
  2222                              <1>             %if %0 = 4
  2223                              <1>                mov edx, %4   
  2224                              <1>             %endif
  2225                              <1>         %endif
  2226                              <1>     %endif
  2227                              <1>     int 30h	   
  2228                              <1> %endmacro
  2229                              <1> 
  2230                              <1> ; 13/05/2015 - ERROR CODES
  2231                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2232                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2233                              <1> ; 14/05/2015
  2234                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2235                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2236                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2237                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2238                              <1> ; 16/05/2015		
  2239                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2240                              <1> ; 18/05/2015
  2241                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2242                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2243                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2244                              <1> ; 07/06/2015
  2245                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2246                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2247                              <1> ; 09/06/2015
  2248                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2249                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2250                              <1> ; 16/06/2015
  2251                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2252                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2253                              <1> ; 22/06/2015
  2254                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2255                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2256                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2257                              <1> ; 23/06/2015
  2258                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2259                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2260                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2261                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2262                              <1> ; 27/06/2015
  2263                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2264                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2265                              <1> ; 29/06/2015
  2266                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2267                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2268                              <1> ; 08/02/2022 
  2269                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2270                              <1> ; 10/10/2016
  2271                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2272                              <1> ; 18/05/2016
  2273                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2274                              <1> ; 15/10/2016
  2275                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2276                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2277                              <1> ; 16/10/2016
  2278                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2279                              <1> ; 08/02/2022
  2280                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2281                              <1> 
  2282                              <1> ; 13/06/2022
  2283                              <1> ; printer errors
  2284                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2285                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2286                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2287                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2288                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error
  2289                              <1> 
  2290                              <1> ; 26/08/2015
  2291                              <1> ; 24/07/2015
  2292                              <1> ; 24/06/2015
  2293                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2294                              <1> ; 01/07/2015
  2295                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2296                              <1> ; 24/12/2021
  2297                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2113                                  %include 'u0.s'        ; 15/03/2015
  2114                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS0.INC
  2115                              <1> ; Last Modification: 17/07/2022
  2116                              <1> ; ----------------------------------------------------------------------------
  2117                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2118                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2119                              <1> ;
  2120                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2121                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2122                              <1> ; <Bell Laboratories (17/3/1972)>
  2123                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2124                              <1> ;
  2125                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2126                              <1> ;
  2127                              <1> ; ****************************************************************************
  2128                              <1> 
  2129                              <1> sys_init:
  2130                              <1> 	; 26/02/2022
  2131                              <1> 	; 08/01/2022
  2132                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2133                              <1> 	; 18/10/2015
  2134                              <1> 	; 28/08/2015
  2135                              <1> 	; 24/08/2015
  2136                              <1> 	; 14/08/2015
  2137                              <1> 	; 24/07/2015 
  2138                              <1> 	; 02/07/2015
  2139                              <1> 	; 01/07/2015
  2140                              <1> 	; 23/06/2015
  2141                              <1> 	; 15/04/2015
  2142                              <1> 	; 13/03/2015
  2143                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2144                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2145                              <1> 	;
  2146                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2147                              <1> 	;
  2148                              <1> 	; 14/02/2014
  2149                              <1> 	; 14/07/2013
  2150                              <1> 	;;mov	ax, 41
  2151                              <1> 	; 24/12/2021
  2152                              <1> 	;xor	eax, eax
  2153                              <1> 	;mov	al, 41
  2154                              <1> 	;mov	[rootdir], ax
  2155                              <1> 	;mov	[u.cdir], ax
  2156                              <1> 	;;and	al, 1 ; 15/04/2015
  2157                              <1> 	;inc	al  ; ax = 1
  2158 000028B6 B001                <1> 	mov	al, 1
  2159 000028B8 A2[3B650000]        <1> 	mov	[u.uno], al
  2160                              <1> 	;mov	[mpid], ax
  2161                              <1> 	;mov	[p.pid], ax
  2162 000028BD A2[DA640000]        <1> 	mov	[mpid], al
  2163 000028C2 A2[04620000]        <1> 	mov	[p.pid], al	
  2164 000028C7 A2[64620000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2165                              <1> 	; 24/12/2021
  2166 000028CC B029                <1> 	mov	al, 41
  2167                              <1> 	;mov	[rootdir], ax
  2168                              <1> 	;mov	[u.cdir], ax
  2169 000028CE A2[DC640000]        <1> 	mov	[rootdir], al
  2170 000028D3 A2[F0640000]        <1> 	mov	[u.cdir], al
  2171                              <1> 	;
  2172 000028D8 B004                <1> 	mov	al, time_count ; 30/08/2013
  2173 000028DA A2[2E650000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2174                              <1> 	; 02/07/2015
  2175 000028DF A1[28610000]        <1> 	mov	eax, [k_page_dir]
  2176                              <1> 	;sub	eax, eax
  2177 000028E4 A3[45650000]        <1> 	mov	[u.pgdir], eax ; reset
  2178                              <1> 	; 18/10/2015
  2179                              <1> 	;mov	[u.ppgdir], eax ; 0
  2180                              <1> 	; 26/02/2022
  2181                              <1>  	;call	epoch
  2182                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2183                              <1> 	; 17/07/2013
  2184 000028E9 E881060000          <1> 	call 	bf_init ; buffer initialization
  2185                              <1> 	; 26/02/2022
  2186                              <1> 	; (save sysinit time on sb0)
  2187 000028EE E829030000          <1> 	call	epoch
  2188 000028F3 A3[48770000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2189                              <1> 	; 23/06/2015
  2190 000028F8 E8C4FAFFFF          <1> 	call	allocate_page
  2191                              <1> 	;;jc	error
  2192                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2193                              <1> 	; 24/12/2021
  2194 000028FD 7305                <1> 	jnc	short sysinit_1
  2195 000028FF E989000000          <1> 	jmp	panic
  2196                              <1> sysinit_1:
  2197 00002904 A3[3C650000]        <1> 	mov	[u.upage], eax ; user structure page	
  2198 00002909 A3[74620000]        <1> 	mov	[p.upage], eax
  2199                              <1> 	;
  2200 0000290E E81FFBFFFF          <1> 	call	clear_page
  2201                              <1> 	;
  2202                              <1> 	; 14/08/2015
  2203 00002913 FA                  <1> 	cli
  2204                              <1> 	; 14/03/2015
  2205                              <1> 	; 17/01/2014
  2206 00002914 E8D0010000          <1> 	call	sp_init ; serial port initialization
  2207                              <1> 	; 14/08/2015
  2208 00002919 FB                  <1> 	sti
  2209                              <1> 	;
  2210                              <1> 	; 30/06/2015
  2211                              <1> 	;mov	esi, kernel_init_ok_msg
  2212                              <1> 	;call 	print_msg
  2213                              <1> 	;
  2214 0000291A 30DB                <1> 	xor	bl, bl ; video page 0
  2215                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2216 0000291C E8410F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2217 00002921 FEC3                <1> 	inc	bl
  2218 00002923 80FB08              <1> 	cmp	bl, 8
  2219 00002926 72F4                <1> 	jb	short vp_clr_nxt
  2220                              <1> 	;
  2221                              <1> 	; 24/07/2015
  2222                              <1> 	;push    KDATA
  2223                              <1>         ;push    esp
  2224                              <1> 	;mov	[tss.esp0], esp
  2225                              <1>         ;mov     word [tss.ss0], KDATA
  2226                              <1> 	;
  2227                              <1> 	; 08/01/2022
  2228                              <1> 	; 24/08/2015
  2229                              <1> 	;; temporary (01/07/2015)
  2230                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2231                              <1> 			       ; it is not needed here !
  2232                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2233 00002928 FE0D[E3640000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2234                              <1> 			      ; 0 = executing a system call
  2235                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2236                              <1> 	;
  2237                              <1> 	;;; 06/08/2015
  2238                              <1> 	;;;call	getch ; wait for a key stroke
  2239                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2240                              <1> ;;sys_init_msg_wait:
  2241                              <1> ;;	push 	ecx
  2242                              <1> ;;	mov	al, 1
  2243                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2244                              <1> ;;	call	getc_n
  2245                              <1> ;;	pop	ecx
  2246                              <1> ;;	jnz	short sys_init_msg_ok
  2247                              <1> ;;	loop	sys_init_msg_wait
  2248                              <1> 	;
  2249                              <1> ;;sys_init_msg_ok:
  2250                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2251 0000292E 6A10                <1> 	push	KDATA ; ss
  2252 00002930 54                  <1> 	push	esp
  2253 00002931 9C                  <1> 	pushfd
  2254 00002932 6A08                <1> 	push	KCODE ; cs
  2255 00002934 68[61290000]        <1> 	push	init_exec ; eip
  2256 00002939 8925[E4640000]      <1> 	mov	[u.sp], esp
  2257 0000293F 1E                  <1> 	push	ds
  2258 00002940 06                  <1> 	push	es
  2259 00002941 0FA0                <1> 	push	fs
  2260 00002943 0FA8                <1> 	push	gs	
  2261 00002945 60                  <1> 	pushad
  2262 00002946 8925[E8640000]      <1> 	mov	[u.usp], esp
  2263 0000294C E8AD1B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2264                              <1> 		      ; and interrupt return components (for IRET)
  2265 00002951 61                  <1> 	popad
  2266 00002952 6658                <1> 	pop	ax ; gs
  2267 00002954 6658                <1> 	pop	ax ; fs
  2268 00002956 6658                <1> 	pop	ax ; es
  2269 00002958 6658                <1> 	pop	ax ; ds	
  2270 0000295A 58                  <1> 	pop	eax ; eip (init_exec)
  2271 0000295B 6658                <1> 	pop	ax ; cs (KCODE)
  2272 0000295D 58                  <1> 	pop	eax ; E-FLAGS
  2273 0000295E 58                  <1> 	pop	eax ; esp
  2274 0000295F 6658                <1> 	pop	ax ; ss (KDATA)
  2275                              <1> 	;
  2276                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2277                              <1> 	;xor	eax, eax ; 0
  2278                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2279                              <1> 	;
  2280                              <1> 	; 02/07/2015
  2281                              <1> 	; [u.pgdir ] = [k_page_dir]
  2282                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2283                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2284                              <1> init_exec:
  2285                              <1> 	; 13/03/2013
  2286                              <1> 	; 24/07/2013
  2287 00002961 BB[83290000]        <1> 	mov	ebx, init_file
  2288 00002966 B9[7B290000]        <1> 	mov	ecx, init_argp
  2289                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2290                              <1> 	; ECX contains address of argument list pointer
  2291                              <1> 	;
  2292                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2293                              <1> 			      ; 0 = executing a system call
  2294                              <1> 	sys	_exec  ; execute file
  2215                              <2> 
  2216                              <2> 
  2217 0000296B B80B000000          <2>  mov eax, %1
  2218                              <2>  %if %0 >= 2
  2219                              <2>  mov ebx, %2
  2220                              <2>  %if %0 >= 3
  2221                              <2>  mov ecx, %3
  2222                              <2>  %if %0 = 4
  2223                              <2>  mov edx, %4
  2224                              <2>  %endif
  2225                              <2>  %endif
  2226                              <2>  %endif
  2227 00002970 CD30                <2>  int 30h
  2295 00002972 7319                <1> 	jnc	short panic
  2296                              <1> 	;
  2297 00002974 BE[405E0000]        <1> 	mov	esi, etc_init_err_msg
  2298                              <1> 	; 08/01/2022
  2299                              <1> 	;call 	print_msg
  2300 00002979 EB17                <1> 	jmp	short key_to_reboot
  2301                              <1> 
  2302                              <1> ;align 4
  2303                              <1> init_argp:
  2304 0000297B [83290000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2305                              <1> init_file:
  2306                              <1> 	; 24/08/2015
  2307 00002983 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2307 0000298C 00                  <1>
  2308                              <1> panic:
  2309                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2310                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2311 0000298D BE[255E0000]        <1> 	mov 	esi, panic_msg
  2312                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2313 00002992 E819000000          <1> 	call 	print_msg
  2314                              <1> ;key_to_reboot:
  2315                              <1> 	; 15/11/2015
  2316 00002997 E8D82B0000          <1> 	call 	getch 
  2317                              <1> 		; wait for a character from the current tty
  2318                              <1> 	;
  2319 0000299C B00A                <1> 	mov	al, 0Ah
  2320 0000299E 8A1D[56610000]      <1> 	mov	bl, [ptty] ; [active_page]
  2321 000029A4 B407                <1> 	mov	ah, 07h ; Black background, 
  2322                              <1> 			; light gray forecolor
  2323 000029A6 E8F1E8FFFF          <1> 	call 	write_tty
  2324 000029AB E990E5FFFF          <1> 	jmp	cpu_reset 
  2325                              <1> 
  2326                              <1> print_msg:
  2327                              <1> 	; 01/07/2015
  2328                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2329                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2330                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2331                              <1> 	;
  2332                              <1> 	;
  2333 000029B0 AC                  <1> 	lodsb
  2334                              <1> pmsg1:
  2335 000029B1 56                  <1> 	push 	esi
  2336 000029B2 0FB61D[56610000]    <1> 	movzx	ebx, byte [ptty]
  2337 000029B9 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2338 000029BB E8DCE8FFFF          <1> 	call 	write_tty
  2339 000029C0 5E                  <1> 	pop	esi
  2340 000029C1 AC                  <1> 	lodsb
  2341 000029C2 20C0                <1> 	and 	al, al
  2342 000029C4 75EB                <1> 	jnz 	short pmsg1
  2343 000029C6 C3                  <1> 	retn
  2344                              <1> 	
  2345                              <1> ctrlbrk:
  2346                              <1> 	; 04/02/2022
  2347                              <1> 	; 01/02/2022
  2348                              <1> 	; 12/11/2015
  2349                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2350                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2351                              <1> 	;
  2352                              <1> 	; INT 1Bh (control+break) handler
  2353                              <1> 	;
  2354                              <1>       	; Retro Unix 8086 v1 feature only!
  2355                              <1>       	;
  2356 000029C7 66833D[30650000]00  <1> 	cmp 	word [u.intr], 0
  2357 000029CF 764B                <1> 	jna 	short cbrk4
  2358                              <1> cbrk0:
  2359                              <1> 	; 12/11/2015
  2360                              <1> 	; 06/12/2013
  2361 000029D1 66833D[32650000]00  <1> 	cmp 	word [u.quit], 0
  2362 000029D9 7441                <1> 	jz	short cbrk4
  2363                              <1> 	;
  2364                              <1> 	; 20/09/2013	
  2365                              <1> 	;push 	ax
  2366                              <1> 	; 01/02/2022
  2367 000029DB 50                  <1> 	push	eax
  2368                              <1> 
  2369                              <1> 	; 04/02/2022
  2370                              <1> 	; (repetitive ctrl+brk check) 
  2371 000029DC 66A1[32650000]      <1> 	mov	ax, [u.quit]
  2372 000029E2 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2373 000029E4 7435                <1> 	jz	short cbrk3
  2374                              <1> 
  2375                              <1> 	; 20/09/2013
  2376 000029E6 A0[56610000]        <1> 	mov	al, [ptty]
  2377                              <1> 	;
  2378                              <1> 	; 12/11/2015
  2379                              <1> 	;
  2380                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2381                              <1> 	; or ctrl+break from console (pseudo) tty
  2382                              <1> 	; (!redirection!)
  2383                              <1> 	;
  2384 000029EB 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2385 000029ED 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2386                              <1> 	;	
  2387                              <1> 	; Serial port interrupt handler sets [ptty]
  2388                              <1> 	; to the port's tty number (as temporary).
  2389                              <1> 	;
  2390                              <1> 	; If active process is using a stdin or 
  2391                              <1> 	; stdout redirection (by the shell),
  2392                              <1>         ; console tty keyboard must be available
  2393                              <1> 	; to terminate running process,
  2394                              <1> 	; in order to prevent a deadlock. 
  2395                              <1> 	;
  2396 000029EF 52                  <1> 	push	edx
  2397 000029F0 0FB615[3B650000]    <1> 	movzx	edx, byte [u.uno]
  2398 000029F7 3A82[43620000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2399 000029FD 5A                  <1> 	pop	edx
  2400 000029FE 7412                <1> 	je	short cbrk2
  2401                              <1> cbrk1:
  2402 00002A00 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2403                              <1> 	; 06/12/2013
  2404 00002A02 3A05[1C650000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2405 00002A08 7408                <1> 	je	short cbrk2	
  2406 00002A0A 3A05[1D650000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2407 00002A10 7509                <1> 	jne	short cbrk3	
  2408                              <1> cbrk2:
  2409                              <1> 	;; 06/12/2013
  2410                              <1> 	;mov	ax, [u.quit]
  2411                              <1> 	;and	ax, ax
  2412                              <1> 	;jz	short cbrk3
  2413                              <1> 	;
  2414                              <1> 	;xor	ax, ax ; 0
  2415                              <1> 	;dec	ax
  2416                              <1> 	; 01/02/2022
  2417 00002A12 31C0                <1> 	xor	eax, eax ; 0
  2418 00002A14 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2419                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2420 00002A15 66A3[32650000]      <1> 	mov	[u.quit], ax
  2421                              <1> cbrk3:
  2422                              <1> 	;pop	ax
  2423                              <1> 	; 01/02/2022
  2424 00002A1B 58                  <1> 	pop	eax
  2425                              <1> cbrk4:
  2426 00002A1C C3                  <1> 	retn
  2427                              <1> 
  2428                              <1> com2_int:
  2429                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2430                              <1> 	; 07/11/2015 
  2431                              <1> 	; 24/10/2015
  2432                              <1> 	; 23/10/2015
  2433                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2434                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2435                              <1> 	; < serial port 2 interrupt handler >
  2436                              <1> 	;
  2437 00002A1D 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2438                              <1> 	;;push	eax
  2439                              <1> 	; 08/01/2022
  2440 00002A20 29C0                <1> 	sub	eax, eax
  2441 00002A22 B009                <1> 	mov	al, 9
  2442                              <1> 	;mov	ax, 9
  2443 00002A24 EB07                <1> 	jmp	short comm_int
  2444                              <1> com1_int:
  2445                              <1> 	; 07/11/2015
  2446                              <1> 	; 24/10/2015
  2447 00002A26 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2448                              <1> 	; 23/10/2015
  2449                              <1> 	;push	eax
  2450                              <1> 	; 08/01/2022
  2451 00002A29 29C0                <1> 	sub	eax, eax
  2452 00002A2B B008                <1> 	mov	al, 8
  2453                              <1> 	;mov	ax, 8
  2454                              <1> comm_int:
  2455                              <1> 	; 08/01/2022
  2456                              <1> 	; 20/11/2015
  2457                              <1> 	; 18/11/2015
  2458                              <1> 	; 17/11/2015
  2459                              <1> 	; 16/11/2015
  2460                              <1> 	; 09/11/2015
  2461                              <1> 	; 08/11/2015
  2462                              <1> 	; 07/11/2015
  2463                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2464                              <1> 	; 01/11/2015
  2465                              <1> 	; 26/10/2015
  2466                              <1> 	; 23/10/2015
  2467 00002A2D 53                  <1> 	push	ebx
  2468 00002A2E 56                  <1> 	push	esi
  2469 00002A2F 57                  <1> 	push	edi
  2470 00002A30 1E                  <1> 	push 	ds
  2471 00002A31 06                  <1> 	push 	es
  2472                              <1> 	; 18/11/2015
  2473 00002A32 0F20DB              <1> 	mov	ebx, cr3
  2474 00002A35 53                  <1> 	push	ebx ; ****
  2475                              <1> 	;
  2476 00002A36 51                  <1> 	push	ecx ; ***
  2477 00002A37 52                  <1> 	push	edx ; **
  2478                              <1> 	;
  2479 00002A38 BB10000000          <1> 	mov	ebx, KDATA
  2480 00002A3D 8EDB                <1> 	mov	ds, bx
  2481 00002A3F 8EC3                <1> 	mov	es, bx
  2482                              <1> 	;
  2483 00002A41 8B0D[28610000]      <1> 	mov	ecx, [k_page_dir]
  2484 00002A47 0F22D9              <1> 	mov	cr3, ecx
  2485                              <1> 	; 20/11/2015
  2486                              <1> 	; Interrupt identification register
  2487 00002A4A 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2488                              <1> 	;
  2489 00002A4E 3C08                <1> 	cmp 	al, 8 
  2490 00002A50 7702                <1> 	ja 	short com_i0
  2491                              <1> 	;
  2492                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2493                              <1> 	; 20/11/2015
  2494                              <1> 	; 17/11/2015
  2495                              <1> 	; 16/11/2015
  2496                              <1> 	; 15/11/2015
  2497                              <1> 	; 24/10/2015
  2498                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2499                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2500                              <1> 	; < serial port 1 interrupt handler >
  2501                              <1> 	;
  2502 00002A52 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2503                              <1> com_i0:
  2504                              <1> 	;push	eax ; *
  2505                              <1> 	; 07/11/2015
  2506 00002A54 A2[96610000]        <1> 	mov 	byte [ccomport], al
  2507                              <1> 	; 09/11/2015
  2508                              <1> 	;movzx	ebx, ax ; 8 or 9
  2509                              <1> 	; 08/01/2022
  2510 00002A59 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2511                              <1> 	; 17/11/2015
  2512                              <1>  	; reset request for response status
  2513 00002A5B 88A3[8C610000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2514                              <1> 	;
  2515                              <1> 	; 20/11/2015
  2516 00002A61 EC                  <1> 	in	al, dx		; read interrupt id. register
  2517 00002A62 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2518 00002A64 2404                <1> 	and	al, 4		; received data available?	
  2519 00002A66 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2520                              <1> 	;
  2521                              <1> 	; 20/11/2015
  2522 00002A68 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2523 00002A6B EC                  <1> 	in	al, dx     	; read character
  2524                              <1> 	;JMP	$+2	   	; I/O DELAY
  2525                              <1> 	; 08/11/2015
  2526                              <1> 	; 07/11/2015
  2527 00002A6C 89DE                <1> 	mov	esi, ebx 
  2528 00002A6E 89DF                <1> 	mov	edi, ebx
  2529 00002A70 81C6[90610000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2530 00002A76 81C7[92610000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2531 00002A7C 8806                <1> 	mov	[esi], al ; received char (current char)
  2532                              <1> 	; query
  2533 00002A7E 20C0                <1> 	and	al, al
  2534 00002A80 7527                <1> 	jnz	short com_i2
  2535                              <1>    	; response
  2536                              <1> 	; 17/11/2015
  2537                              <1> 	; set request for response status
  2538 00002A82 FE83[8C610000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2539                              <1> 	;
  2540 00002A88 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2541 00002A8C EC                  <1> 	in	al, dx	   	; read line status register 
  2542 00002A8D EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2543 00002A8F 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2544 00002A91 7445                <1> 	jz	short com_eoi 	; no
  2545 00002A93 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2546 00002A95 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2547 00002A99 EE                  <1> 	out	dx, al	   	; send on serial port
  2548                              <1> 	; 17/11/2015
  2549 00002A9A 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2550 00002A9D 7502                <1> 	jne 	short com_i1    ; no
  2551 00002A9F 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2552                              <1> com_i1:
  2553                              <1> 	; 17/11/2015
  2554                              <1> 	; reset request for response status (again)
  2555 00002AA1 FE8B[8C610000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2556 00002AA7 EB2F                <1> 	jmp	short com_eoi
  2557                              <1> com_i2:	
  2558                              <1> 	; 08/11/2015
  2559 00002AA9 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2560 00002AAB 7417                <1> 	je	short com_i3	; (check for response signal)
  2561                              <1> 	; 07/11/2015
  2562 00002AAD 3C04                <1> 	cmp	al, 04h	; EOT
  2563 00002AAF 751C                <1> 	jne	short com_i4	
  2564                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2565                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2566                              <1> 	; 08/11/2015
  2567                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2568 00002AB1 861D[56610000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2569 00002AB7 E80BFFFFFF          <1> 	call 	ctrlbrk
  2570 00002ABC 861D[56610000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2571                              <1> 	;mov	al, 04h ; EOT
  2572                              <1> 	; 08/11/2015
  2573 00002AC2 EB09                <1> 	jmp	short com_i4	
  2574                              <1> com_i3:
  2575                              <1> 	; 08/11/2015
  2576                              <1> 	; If 0FFh has been received just after a query
  2577                              <1> 	; (schar, ZERO), it is a response signal.
  2578                              <1> 	; 17/11/2015
  2579 00002AC4 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2580 00002AC7 7704                <1> 	ja	short com_i4 ; no
  2581                              <1> 	; reset query status (schar)
  2582 00002AC9 8807                <1> 	mov	[edi], al ; 0FFh
  2583 00002ACB FEC0                <1> 	inc	al ; 0
  2584                              <1> com_i4:
  2585                              <1> 	; 27/07/2014
  2586                              <1> 	; 09/07/2014
  2587 00002ACD D0E3                <1> 	shl	bl, 1	
  2588 00002ACF 81C3[58610000]      <1> 	add	ebx, ttychr
  2589                              <1> 	; 23/07/2014 (always overwrite)
  2590                              <1> 	;;cmp	word [ebx], 0
  2591                              <1> 	;;ja	short com_eoi
  2592                              <1> 	;
  2593 00002AD5 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2594                              <1> 			    ; scan code = 0
  2595                              <1> com_eoi:
  2596                              <1> 	;mov	al, 20h
  2597                              <1> 	;out	20h, al	   ; end of interrupt
  2598                              <1> 	;
  2599                              <1> 	; 07/11/2015
  2600                              <1>       	;pop	eax ; *
  2601 00002AD8 A0[96610000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2602                              <1> 	; al = tty number (8 or 9)
  2603 00002ADD E8F61A0000          <1>         call	wakeup
  2604                              <1> com_iret:
  2605                              <1> 	; 23/10/2015
  2606 00002AE2 5A                  <1> 	pop	edx ; **
  2607 00002AE3 59                  <1> 	pop	ecx ; ***
  2608                              <1> 	; 18/11/2015
  2609                              <1> 	;pop	eax ; ****
  2610                              <1> 	;mov	cr3, eax
  2611                              <1> 	;jmp	iiret
  2612 00002AE4 E99BDEFFFF          <1> 	jmp	iiretp
  2613                              <1> 
  2614                              <1> ;iiretp: ; 01/09/2015
  2615                              <1> ;	; 28/08/2015
  2616                              <1> ;	pop	eax ; (*) page directory
  2617                              <1> ;	mov	cr3, eax
  2618                              <1> ;iiret:
  2619                              <1> ;	; 22/08/2014
  2620                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2621                              <1> ;	out	20h, al	; 8259 PORT
  2622                              <1> ;	;
  2623                              <1> ;	pop	es
  2624                              <1> ;	pop	ds
  2625                              <1> ;	pop	edi
  2626                              <1> ;	pop	esi
  2627                              <1> ;	pop	ebx ; 29/08/2014
  2628                              <1> ;	pop 	eax
  2629                              <1> ;	iretd
  2630                              <1> 
  2631                              <1> sp_init:
  2632                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2633                              <1> 	; 07/11/2015
  2634                              <1> 	; 29/10/2015
  2635                              <1> 	; 26/10/2015
  2636                              <1> 	; 23/10/2015
  2637                              <1> 	; 29/06/2015
  2638                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2639                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2640                              <1> 	; Initialization of Serial Port Communication Parameters
  2641                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2642                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2643                              <1> 	;
  2644                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2645                              <1> 	;
  2646                              <1> 	; INPUT:  (29/06/2015)
  2647                              <1> 	;	AL = 0 for COM1
  2648                              <1> 	;	     1 for COM2
  2649                              <1> 	;	AH = Communication parameters	
  2650                              <1> 	;
  2651                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2652                              <1> 	;	Bit	4	3	2	1	0
  2653                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2654                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2655                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2656                              <1> 	;		11 = even
  2657                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2658                              <1> 	;		Retro UNIX 386 v1 feature only !
  2659                              <1> 	;	Bit	7    6    5  | Baud rate
  2660                              <1> 	;		------------------------
  2661                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2662                              <1> 	;		0    0    1  | 9600 (12)
  2663                              <1> 	;		0    1    0  | 19200 (6) 
  2664                              <1> 	;		0    1	  1  | 38400 (3) 
  2665                              <1> 	;		1    0	  0  | 14400 (8)
  2666                              <1> 	;		1    0	  1  | 28800 (4)
  2667                              <1> 	;		1    1    0  | 57600 (2)
  2668                              <1> 	;		1    1    1  | 115200 (1) 	
  2669                              <1> 	
  2670                              <1> 	; References:	
  2671                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2672                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2673                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2674                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2675                              <1> 	;
  2676                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2677                              <1> 	;
  2678 00002AE9 BB[92610000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2679 00002AEE 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2680                              <1> 	; 29/10/2015
  2681 00002AF2 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2682 00002AF6 E84F000000          <1> 	call	sp_i3	; call A4	
  2683 00002AFB A880                <1> 	test	al, 80h
  2684 00002AFD 740E                <1> 	jz	short sp_i0 ; OK..
  2685                              <1> 		; Error !
  2686                              <1> 	;mov	dx, 3F8h
  2687 00002AFF 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2688                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2689                              <1> 	; 08/01/2022
  2690 00002B02 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2691 00002B04 E841000000          <1> 	call	sp_i3	; call A4	
  2692 00002B09 A880                <1> 	test	al, 80h
  2693 00002B0B 7508                <1> 	jnz	short sp_i1
  2694                              <1> sp_i0:
  2695                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2696                              <1>         ; (INT 14h initialization code disables interrupts.)
  2697                              <1> 	;
  2698 00002B0D C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2699 00002B10 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2700                              <1> sp_i1:
  2701 00002B15 43                  <1> 	inc	ebx
  2702 00002B16 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2703                              <1> 	; 29/10/2015
  2704                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2705                              <1> 	; 08/01/2022
  2706 00002B1A B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2707 00002B1C E829000000          <1> 	call	sp_i3	; call A4	
  2708 00002B21 A880                <1> 	test	al, 80h
  2709 00002B23 740E                <1> 	jz	short sp_i2 ; OK..
  2710                              <1> 		; Error !
  2711                              <1> 	;mov	dx, 2F8h
  2712 00002B25 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2713                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2714                              <1> 	; 08/01/2022
  2715 00002B28 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2716 00002B2A E81B000000          <1> 	call	sp_i3	; call A4	
  2717 00002B2F A880                <1> 	test	al, 80h
  2718 00002B31 7516                <1> 	jnz	short sp_i7
  2719                              <1> sp_i2:
  2720 00002B33 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2721                              <1> sp_i6:
  2722                              <1> 	;; COM2 - enabling IRQ 3
  2723                              <1> 	; 08/01/2022
  2724 00002B36 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2725                              <1> 	; 07/11/2015
  2726                              <1> 	; 26/10/2015
  2727                              <1> 	;pushf
  2728                              <1> 	;cli
  2729                              <1> 	;;
  2730                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2731                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2732                              <1> 	;in	al, dx 	   		; read register
  2733                              <1> 	;JMP	$+2	   		; I/O DELAY
  2734                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2735                              <1> 	;out	dx, al     		; write back to register
  2736                              <1> 	;JMP	$+2	   		; I/O DELAY
  2737                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2738                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2739                              <1> 	;in	al, dx     		; read register
  2740                              <1> 	;JMP	$+2	   		; I/O DELAY
  2741                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2742                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2743                              <1> 	;out	dx, al 	   		; write back to register
  2744                              <1> 	;JMP	$+2        		; I/O DELAY
  2745                              <1> 	;in	al, 21h    		; read interrupt mask register
  2746                              <1> 	;JMP	$+2	   		; I/O DELAY
  2747                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2748                              <1> 	;out	21h, al    		; write back to register
  2749                              <1> 	;
  2750                              <1> 	; 08/01/2022
  2751 00002B38 9C                  <1> 	pushf
  2752 00002B39 E8AA000000          <1> 	call	sp_i8
  2753                              <1> 	; 23/10/2015
  2754 00002B3E B8[1D2A0000]        <1> 	mov 	eax, com2_int
  2755 00002B43 A3[CE2F0000]        <1> 	mov	[com2_irq3], eax
  2756                              <1> 	; 26/10/2015
  2757 00002B48 9D                  <1> 	popf	
  2758                              <1> sp_i7:
  2759 00002B49 C3                  <1> 	retn
  2760                              <1> 
  2761                              <1> sp_i3:
  2762                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2763                              <1> 	; 28/10/2015
  2764 00002B4A FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2765 00002B4C B000                <1> 	mov	al, 0
  2766 00002B4E EE                  <1> 	out	dx, al			; disable serial port interrupt
  2767 00002B4F EB00                <1> 	JMP	$+2			; I/O DELAY
  2768 00002B51 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2769 00002B54 B080                <1> 	mov	al, 80h			
  2770 00002B56 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2771                              <1> 	;-----	SET BAUD RATE DIVISOR
  2772                              <1> 	; 26/10/2015
  2773 00002B57 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2774                              <1> 					; of the divisor value
  2775 00002B5A 88C8                <1> 	mov	al, cl	; 1
  2776 00002B5C EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2777                              <1> 					; 2 = 57600 baud
  2778                              <1> 					; 3 = 38400 baud
  2779                              <1> 					; 6 = 19200 baud
  2780                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2781 00002B5D EB00                <1> 	JMP	$+2			; I/O DELAY
  2782 00002B5F 28C0                <1> 	sub	al, al
  2783 00002B61 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2784                              <1> 					; of the divisor value
  2785 00002B63 EE                  <1> 	out	dx, al ; 0
  2786 00002B64 EB00                <1> 	JMP	$+2			; I/O DELAY
  2787                              <1> 	;	
  2788 00002B66 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2789                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2790 00002B68 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2791 00002B6B EE                  <1> 	out	dx, al			
  2792 00002B6C EB00                <1> 	JMP	$+2			; I/O DELAY
  2793                              <1> 	; 29/10/2015
  2794 00002B6E FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2795 00002B70 30C0                <1> 	xor	al, al			; 0
  2796 00002B72 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2797 00002B73 EB00                <1> 	JMP	$+2	
  2798                              <1> sp_i4:
  2799                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2800                              <1> 	; 29/06/2015 (line status after modem status)
  2801 00002B75 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2802                              <1> sp_i4s:
  2803 00002B78 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2804 00002B79 EB00                <1> 	JMP	$+2			; I/O DELAY
  2805 00002B7B 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2806 00002B7D FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2807                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2808 00002B7F EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2809                              <1> 	; AL = Line status, AH = Modem status
  2810 00002B80 C3                  <1> 	retn
  2811                              <1> 
  2812                              <1> sp_status:
  2813                              <1> 	; 29/06/2015
  2814                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2815                              <1> 	; Get serial port status
  2816 00002B81 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2817 00002B85 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2818                              <1> 					; dx = 2FEh for COM2
  2819 00002B87 EBEF                <1> 	jmp	short sp_i4s
  2820                              <1> 
  2821                              <1> sp_setp: ; Set serial port communication parameters
  2822                              <1> 	; 08/01/2022
  2823                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2824                              <1> 	; 07/11/2015
  2825                              <1> 	; 29/10/2015
  2826                              <1> 	; 29/06/2015
  2827                              <1> 	; Retro UNIX 386 v1 feature only !	
  2828                              <1> 	;
  2829                              <1> 	; INPUT:
  2830                              <1> 	;	AL = 0 for COM1
  2831                              <1> 	;	     1 for COM2
  2832                              <1> 	;	AH = Communication parameters (*)
  2833                              <1> 	; OUTPUT:
  2834                              <1> 	;	CL = Line status
  2835                              <1> 	;	CH = Modem status
  2836                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2837                              <1> 	;		 'invalid parameter !' 
  2838                              <1> 	;		 	 or
  2839                              <1> 	;		 'device not ready !' error
  2840                              <1> 	;	
  2841                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2842                              <1> 	;	Bit	4	3	2	1	0
  2843                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2844                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2845                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2846                              <1> 	;		11 = even
  2847                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2848                              <1> 	;		Retro UNIX 386 v1 feature only !
  2849                              <1> 	;	Bit	7    6    5  | Baud rate
  2850                              <1> 	;		------------------------
  2851                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2852                              <1> 	;		0    0    1  | 9600 (12)
  2853                              <1> 	;		0    1    0  | 19200 (6) 
  2854                              <1> 	;		0    1	  1  | 38400 (3) 
  2855                              <1> 	;		1    0	  0  | 14400 (8)
  2856                              <1> 	;		1    0	  1  | 28800 (4)
  2857                              <1> 	;		1    1    0  | 57600 (2)
  2858                              <1> 	;		1    1    1  | 115200 (1) 
  2859                              <1> 	;
  2860                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2861                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2862                              <1> 	;
  2863                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2864                              <1> 	;
  2865 00002B89 66BAF803            <1> 	mov	dx, 3F8h
  2866 00002B8D BB[92610000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2867 00002B92 3C01                <1> 	cmp	al, 1
  2868 00002B94 7770                <1> 	ja 	short sp_invp_err
  2869 00002B96 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2870 00002B98 FECE                <1> 	dec	dh ; 2F8h
  2871 00002B9A 43                  <1> 	inc	ebx ; COM2 control byte offset
  2872                              <1> sp_setp1:
  2873                              <1> 	; 29/10/2015
  2874 00002B9B 8823                <1> 	mov	[ebx], ah
  2875 00002B9D 0FB6CC              <1> 	movzx 	ecx, ah
  2876 00002BA0 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2877 00002BA3 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2878 00002BA6 8A81[152C0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2879 00002BAC 6689C1              <1> 	mov	cx, ax
  2880 00002BAF E896FFFFFF          <1> 	call	sp_i3
  2881 00002BB4 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2882 00002BB7 A880                <1> 	test	al, 80h
  2883 00002BB9 740F                <1> 	jz	short sp_setp2
  2884 00002BBB C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2885                              <1> stp_dnr_err:
  2886 00002BBE C705[41650000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2886 00002BC6 0000                <1>
  2887                              <1> 	; CL = Line status, CH = Modem status
  2888 00002BC8 F9                  <1> 	stc
  2889 00002BC9 C3                  <1> 	retn
  2890                              <1> sp_setp2:
  2891 00002BCA 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2892                              <1>         ;jna	sp_i6
  2893                              <1> 		      ; COM1 (3F?h)
  2894                              <1> 	; 24/12/2021
  2895 00002BCD 7705                <1> 	ja	short sp_i5
  2896 00002BCF E962FFFFFF          <1> 	jmp	sp_i6
  2897                              <1> sp_i5: 
  2898                              <1> 	; 08/01/2022
  2899 00002BD4 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2900                              <1> 	; 07/11/2015
  2901                              <1> 	; 26/10/2015
  2902                              <1> 	; 29/06/2015
  2903                              <1> 	;
  2904                              <1> 	;; COM1 - enabling IRQ 4
  2905                              <1> 	;pushf
  2906                              <1> 	;cli
  2907                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2908                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2909                              <1> 	;in	al, dx 	   		; read register
  2910                              <1> 	;JMP	$+2			; I/O DELAY
  2911                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2912                              <1> 	;out	dx, al     		; write back to register
  2913                              <1> 	;JMP	$+2			; I/O DELAY
  2914                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2915                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2916                              <1> 	;in	al, dx     		; read register
  2917                              <1> 	;JMP	$+2			; I/O DELAY
  2918                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2919                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2920                              <1> 	;out	dx, al 	   		; write back to register
  2921                              <1> 	;JMP	$+2        		; I/O DELAY
  2922                              <1> 	;in	al, 21h    		; read interrupt mask register
  2923                              <1> 	;JMP	$+2			; I/O DELAY
  2924                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2925                              <1> 	;out	21h, al    		; write back to register
  2926                              <1> 	;
  2927                              <1> 	; 08/01/2022
  2928 00002BD6 9C                  <1> 	pushf
  2929 00002BD7 E80C000000          <1> 	call	sp_i8
  2930                              <1> 	; 23/10/2015
  2931 00002BDC B8[262A0000]        <1> 	mov 	eax, com1_int
  2932 00002BE1 A3[CA2F0000]        <1> 	mov	[com1_irq4], eax
  2933                              <1> 	; 26/10/2015
  2934 00002BE6 9D                  <1> 	popf
  2935 00002BE7 C3                  <1> 	retn
  2936                              <1> 
  2937                              <1> sp_i8:
  2938                              <1> 	; 08/01/2022
  2939                              <1> 	;pushf
  2940 00002BE8 FA                  <1> 	cli
  2941                              <1> 	;
  2942                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2943 00002BE9 B2FC                <1> 	mov	dl, 0FCh
  2944 00002BEB EC                  <1> 	in	al, dx 	   		; read register
  2945 00002BEC EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2946 00002BEE 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2947 00002BF0 EE                  <1> 	out	dx, al     		; write back to register
  2948 00002BF1 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2949                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2950 00002BF3 B2F9                <1> 	mov	dl, 0F9h
  2951 00002BF5 EC                  <1> 	in	al, dx     		; read register
  2952 00002BF6 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2953                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2954 00002BF8 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2955 00002BFA EE                  <1> 	out	dx, al 	   		; write back to register
  2956 00002BFB EB00                <1> 	JMP	$+2        		; I/O DELAY
  2957 00002BFD E421                <1> 	in	al, 21h    		; read interrupt mask register
  2958 00002BFF EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2959                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2960 00002C01 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2961 00002C03 E621                <1> 	out	21h, al    		; write back to register
  2962                              <1> 	;
  2963                              <1> 	;popf	
  2964 00002C05 C3                  <1> 	retn
  2965                              <1> 
  2966                              <1> sp_invp_err:
  2967 00002C06 C705[41650000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2967 00002C0E 0000                <1>
  2968 00002C10 31C9                <1> 	xor	ecx, ecx
  2969 00002C12 49                  <1> 	dec	ecx ; 0FFFFh
  2970 00002C13 F9                  <1> 	stc
  2971 00002C14 C3                  <1> 	retn
  2972                              <1> 
  2973                              <1> ; 29/10/2015
  2974                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2975 00002C15 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2976                              <1> 
  2977                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2978                              <1> epoch:
  2979                              <1> 	; 17/07/2022
  2980                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2981                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2982                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2983                              <1> 	; 'epoch' procedure prototype: 
  2984                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2985                              <1> 	; 14/11/2012
  2986                              <1> 	; unixboot.asm (boot file configuration)
  2987                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2988                              <1> 	; 21/7/2012
  2989                              <1> 	; 15/7/2012
  2990                              <1> 	; 14/7/2012		
  2991                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2992                              <1> 	; compute current date and time as UNIX Epoch/Time
  2993                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2994                              <1> 	;
  2995                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2996                              <1> 	;
  2997 00002C1C E818010000          <1> 	call 	get_rtc_time		; Return Current Time
  2998 00002C21 86E9                <1>         xchg 	ch,cl
  2999 00002C23 66890D[985E0000]    <1>         mov 	[hour], cx
  3000 00002C2A 86F2                <1>         xchg 	dh,dl
  3001 00002C2C 668915[9A5E0000]    <1>         mov 	[second], dx
  3002                              <1> 	;
  3003 00002C33 E832010000          <1>         call 	get_rtc_date		; Return Current Date
  3004 00002C38 86E9                <1>         xchg 	ch,cl
  3005 00002C3A 66890D[945E0000]    <1>         mov 	[year], cx
  3006 00002C41 86F2                <1>         xchg 	dh,dl
  3007 00002C43 668915[965E0000]    <1>         mov 	[month], dx
  3008                              <1> 	;
  3009 00002C4A 66B93030            <1> 	mov 	cx, 3030h
  3010                              <1> 	;
  3011 00002C4E A0[985E0000]        <1> 	mov 	al, [hour] ; Hour
  3012                              <1>         	; AL <= BCD number)
  3013 00002C53 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3014                              <1> 					; AH = AL / 10h
  3015                              <1> 					; AL = AL MOD 10h
  3016 00002C55 D50A                <1>         aad 	; AX= AH*10+AL
  3017 00002C57 A2[985E0000]        <1> 	mov 	[hour], al
  3018 00002C5C A0[995E0000]        <1> 	mov 	al, [hour+1] ; Minute
  3019                              <1>         	; AL <= BCD number)
  3020 00002C61 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3021                              <1> 					; AH = AL / 10h
  3022                              <1> 					; AL = AL MOD 10h
  3023 00002C63 D50A                <1>         aad 	; AX= AH*10+AL
  3024 00002C65 A2[995E0000]        <1> 	mov 	[minute], al
  3025 00002C6A A0[9A5E0000]        <1> 	mov 	al, [second] ; Second
  3026                              <1>         	; AL <= BCD number)
  3027 00002C6F D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3028                              <1> 					; AH = AL / 10h
  3029                              <1> 					; AL = AL MOD 10h
  3030 00002C71 D50A                <1>         aad 	; AX= AH*10+AL
  3031 00002C73 A2[9A5E0000]        <1> 	mov 	[second], al
  3032 00002C78 66A1[945E0000]      <1> 	mov 	ax, [year] ; Year (century)
  3033                              <1>  	;push 	ax
  3034                              <1> 	; 08/01/2022
  3035 00002C7E 50                  <1> 	push	eax
  3036                              <1> 	   	; AL <= BCD number)
  3037 00002C7F D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3038                              <1> 					; AH = AL / 10h
  3039                              <1> 					; AL = AL MOD 10h
  3040 00002C81 D50A                <1>         aad 	; AX= AH*10+AL
  3041 00002C83 B464                <1> 	mov 	ah, 100
  3042 00002C85 F6E4                <1> 	mul 	ah
  3043 00002C87 66A3[945E0000]      <1> 	mov 	[year], ax
  3044                              <1> 	;pop	ax
  3045                              <1> 	; 08/01/2022
  3046 00002C8D 58                  <1> 	pop	eax
  3047 00002C8E 88E0                <1> 	mov	al, ah
  3048                              <1>         	; AL <= BCD number)
  3049 00002C90 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3050                              <1> 					; AH = AL / 10h
  3051                              <1> 					; AL = AL MOD 10h
  3052 00002C92 D50A                <1>         aad 	; AX= AH*10+AL
  3053 00002C94 660105[945E0000]    <1> 	add 	[year], ax
  3054 00002C9B A0[965E0000]        <1> 	mov 	al, [month] ; Month
  3055                              <1>            	; AL <= BCD number)
  3056 00002CA0 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3057                              <1> 					; AH = AL / 10h
  3058                              <1> 					; AL = AL MOD 10h
  3059 00002CA2 D50A                <1>         aad 	; AX= AH*10+AL
  3060 00002CA4 A2[965E0000]        <1> 	mov 	[month], al	
  3061 00002CA9 A0[975E0000]        <1>         mov     al, [month+1]      	; Day
  3062                              <1>            	; AL <= BCD number)
  3063 00002CAE D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3064                              <1> 					; AH = AL / 10h
  3065                              <1> 					; AL = AL MOD 10h
  3066 00002CB0 D50A                <1>         aad 	; AX= AH*10+AL
  3067 00002CB2 A2[975E0000]        <1>         mov     [day], al
  3068                              <1> 	
  3069                              <1> convert_to_epoch:
  3070                              <1> 	; 17/07/2022
  3071                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3072                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3073                              <1> 	;
  3074                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3075                              <1> 	;
  3076                              <1> 	; Derived from DALLAS Semiconductor
  3077                              <1> 	; Application Note 31 (DS1602/DS1603)
  3078                              <1> 	; 6 May 1998
  3079 00002CB7 29C0                <1> 	sub 	eax, eax
  3080 00002CB9 66A1[945E0000]      <1> 	mov 	ax, [year]
  3081 00002CBF 662DB207            <1> 	sub 	ax, 1970
  3082 00002CC3 BA6D010000          <1> 	mov 	edx, 365
  3083 00002CC8 F7E2                <1> 	mul 	edx
  3084 00002CCA 31DB                <1> 	xor 	ebx, ebx
  3085 00002CCC 8A1D[965E0000]      <1> 	mov 	bl, [month]
  3086 00002CD2 FECB                <1> 	dec 	bl
  3087 00002CD4 D0E3                <1> 	shl 	bl, 1
  3088                              <1> 	;sub	edx, edx
  3089 00002CD6 668B93[9C5E0000]    <1> 	mov 	dx, [EBX+DMonth]
  3090 00002CDD 8A1D[975E0000]      <1>         mov     bl, [day]
  3091 00002CE3 FECB                <1> 	dec 	bl
  3092 00002CE5 01D0                <1> 	add 	eax, edx
  3093 00002CE7 01D8                <1> 	add 	eax, ebx
  3094                              <1> 			; EAX = days since 1/1/1970
  3095 00002CE9 668B15[945E0000]    <1> 	mov 	dx, [year]
  3096 00002CF0 6681EAB107          <1> 	sub 	dx, 1969
  3097                              <1> 	;shr 	dx, 1
  3098                              <1> 	;shr 	dx, 1		
  3099                              <1> 	; 17/07/2022
  3100 00002CF5 C1EA02              <1> 	shr	edx, 2
  3101                              <1> 		; (year-1969)/4
  3102 00002CF8 01D0                <1> 	add 	eax, edx
  3103                              <1> 			; + leap days since 1/1/1970
  3104 00002CFA 803D[965E0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3105 00002D01 7610                <1> 	jna 	short cte1
  3106 00002D03 668B15[945E0000]    <1> 	mov 	dx, [year]
  3107 00002D0A 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3108 00002D0E 7503                <1> 	jnz 	short cte1		
  3109                              <1> 			; and if leap year
  3110 00002D10 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3111                              <1> cte1: 			; compute seconds since 1/1/1970
  3112 00002D13 BA18000000          <1> 	mov 	edx, 24
  3113 00002D18 F7E2                <1> 	mul	edx
  3114 00002D1A 8A15[985E0000]      <1> 	mov 	dl, [hour]
  3115 00002D20 01D0                <1> 	add 	eax, edx
  3116                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3117                              <1> 	;mov	ebx, 60
  3118 00002D22 B33C                <1> 	mov	bl, 60
  3119 00002D24 F7E3                <1> 	mul	ebx
  3120 00002D26 8A15[995E0000]      <1> 	mov 	dl, [minute]
  3121 00002D2C 01D0                <1> 	add 	eax, edx
  3122                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3123                              <1> 	;mov 	ebx, 60
  3124 00002D2E F7E3                <1> 	mul	ebx
  3125 00002D30 8A15[9A5E0000]      <1> 	mov 	dl, [second]
  3126 00002D36 01D0                <1> 	add 	eax, edx
  3127                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3128 00002D38 C3                  <1> 	retn
  3129                              <1> 
  3130                              <1> get_rtc_time:
  3131                              <1> 	; 15/03/2015
  3132                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3133                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3134                              <1> 	; INT 1Ah
  3135                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3136                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3137                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3138                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3139                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3140                              <1> 	;								
  3141                              <1> RTC_20: 				; GET RTC TIME
  3142 00002D39 FA                  <1> 	cli
  3143 00002D3A E8E1DDFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3144 00002D3F 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3145                              <1> 
  3146 00002D41 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3147 00002D43 E8C2DDFFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3148 00002D48 88C6                <1> 	MOV	DH, AL			; SAVE
  3149 00002D4A B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3150 00002D4C E8B9DDFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3151 00002D51 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3152 00002D53 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3153 00002D55 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3154 00002D57 E8AEDDFFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3155 00002D5C 88C1                <1> 	MOV	CL, AL			; SAVE
  3156 00002D5E B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3157 00002D60 E8A5DDFFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3158 00002D65 88C5                <1> 	MOV	CH, AL			; SAVE
  3159 00002D67 F8                  <1> 	CLC				; SET CY= 0
  3160                              <1> RTC_29:
  3161 00002D68 FB                  <1> 	sti
  3162 00002D69 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3163                              <1> 
  3164                              <1> get_rtc_date:
  3165                              <1> 	; 15/03/2015
  3166                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3167                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3168                              <1> 	; INT 1Ah
  3169                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3170                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3171                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3172                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3173                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3174                              <1> 	;
  3175                              <1> RTC_40: 				; GET RTC DATE
  3176 00002D6A FA                  <1> 	cli
  3177 00002D6B E8B0DDFFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3178 00002D70 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3179                              <1> 
  3180 00002D72 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3181 00002D74 E891DDFFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3182 00002D79 88C2                <1> 	MOV	DL, AL			; SAVE
  3183 00002D7B B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3184 00002D7D E888DDFFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3185 00002D82 88C6                <1> 	MOV	DH, AL			; SAVE
  3186 00002D84 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3187 00002D86 E87FDDFFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3188 00002D8B 88C1                <1> 	MOV	CL, AL			; SAVE
  3189 00002D8D B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3190 00002D8F E876DDFFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3191 00002D94 88C5                <1> 	MOV	CH, AL			; SAVE
  3192 00002D96 F8                  <1> 	CLC				; SET CY=0
  3193                              <1> RTC_49:
  3194 00002D97 FB                  <1> 	sti
  3195 00002D98 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3196                              <1> 
  3197                              <1> set_date_time:
  3198                              <1> convert_from_epoch:
  3199                              <1> 	; 02/06/2022
  3200                              <1> 	; 01/06/2022 (BugFix)
  3201                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3202                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3203                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3204                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3205                              <1> 	;
  3206                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3207                              <1> 	;
  3208                              <1> 	; Derived from DALLAS Semiconductor
  3209                              <1> 	; Application Note 31 (DS1602/DS1603)
  3210                              <1> 	; 6 May 1998
  3211                              <1> 	;
  3212                              <1> 	; INPUT:
  3213                              <1> 	; EAX = Unix (Epoch) Time
  3214                              <1> 	;
  3215 00002D99 31D2                <1> 	xor 	edx, edx
  3216                              <1> 	; 02/06/2022
  3217 00002D9B 31C9                <1> 	xor	ecx, ecx
  3218 00002D9D 31DB                <1> 	xor	ebx, ebx
  3219                              <1> 	;mov 	ecx, 60
  3220 00002D9F B13C                <1> 	mov	cl, 60
  3221 00002DA1 F7F1                <1> 	div	ecx
  3222                              <1> 	;mov 	[imin], eax  ; whole minutes
  3223                              <1> 			     ; since 1/1/1970
  3224                              <1> 	;mov 	[second], dx ; leftover seconds
  3225 00002DA3 8815[9A5E0000]      <1> 	mov	[second], dl ; 02/06/2022
  3226 00002DA9 29D2                <1> 	sub 	edx, edx
  3227 00002DAB F7F1                <1> 	div	ecx
  3228                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3229                              <1> 	;		     ; since 1/1/1970
  3230                              <1> 	;mov 	[minute], dx ; leftover minutes
  3231 00002DAD 8815[995E0000]      <1> 	mov	[minute], dl ; 02/06/2022
  3232 00002DB3 31D2                <1> 	xor	edx, edx
  3233                              <1> 	;mov 	cx, 24
  3234 00002DB5 B118                <1> 	mov 	cl, 24
  3235 00002DB7 F7F1                <1> 	div	ecx
  3236                              <1> 	;mov 	[iday], ax   ; whole days
  3237                              <1> 			     ; since 1/1/1970
  3238                              <1> 	;mov 	[hour], dx   ; leftover hours
  3239 00002DB9 8815[985E0000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3240                              <1> 
  3241 00002DBF 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3242                              <1> 			     ; 1/1/1968 	
  3243                              <1> 	;mov 	[iday], ax
  3244 00002DC4 50                  <1> 	push 	eax
  3245 00002DC5 29D2                <1> 	sub	edx, edx
  3246 00002DC7 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3247 00002DCC F7F1                <1> 	div	ecx
  3248 00002DCE 59                  <1> 	pop 	ecx
  3249                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3250                              <1> 	;push	dx
  3251                              <1> 	; 01/06/2022
  3252 00002DCF 52                  <1> 	push 	edx
  3253                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3254 00002DD0 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3255 00002DD4 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3256 00002DD5 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3257                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3258                              <1> 	;mov 	cx, [iday]
  3259 00002DD8 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3260 00002DD9 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3261 00002DDB B96D010000          <1> 	mov 	ecx, 365
  3262 00002DE0 31D2                <1> 	xor	edx, edx
  3263                              <1> 	; EAX = iday-lday, EDX = 0
  3264 00002DE2 F7F1                <1> 	div	ecx
  3265                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3266                              <1> 	;jday = iday - (iyrs*365) - lday
  3267                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3268                              <1> 	;add	eax, 1968
  3269 00002DE4 6605B007            <1> 	add 	ax, 1968     ; compute year
  3270 00002DE8 66A3[945E0000]      <1> 	mov 	[year], ax
  3271                              <1> 	;mov 	cx, dx
  3272                              <1> 	; 02/06/2022
  3273 00002DEE 89D1                <1> 	mov	ecx, edx
  3274                              <1> 	;mov 	dx, [qday]
  3275                              <1> 	;pop	dx
  3276                              <1> 	; 01/06/2022
  3277 00002DF0 5A                  <1> 	pop 	edx
  3278 00002DF1 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3279 00002DF6 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3280 00002DF8 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3281 00002DFC F5                  <1>         cmc		     ; add a leap day to the # of whole
  3282 00002DFD 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3283                              <1> cfe1:			
  3284                              <1> 	;mov 	[jday], cx
  3285                              <1> 	;mov 	bx, 12       ; estimate month
  3286                              <1> 	;sub	ebx, ebx
  3287                              <1> 	; 02/06/2022
  3288 00002E01 B30C                <1> 	mov	bl, 12
  3289 00002E03 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3290 00002E07 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3291                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3292                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3293                              <1> 	; 02/06/2022
  3294 00002E0B 39D1                <1> 	cmp	ecx, edx 	 		
  3295 00002E0D 7319                <1> 	jnb 	short cfe3
  3296                              <1> 	;dec 	bx           ; month = month - 1
  3297 00002E0F FECB                <1> 	dec	bl			
  3298                              <1> 	;shl 	bx, 1
  3299 00002E11 D0E3                <1> 	shl	bl, 1
  3300 00002E13 668B93[9C5E0000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3301                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3302                              <1> 	; 02/06/2022
  3303 00002E1A D0EB                <1> 	shr	bl, 1
  3304 00002E1C 80FB01              <1> 	cmp	bl, 1
  3305                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3306 00002E1F 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3307 00002E21 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3308 00002E23 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3309                              <1> 	;inc 	dx           ; mday = mday + 1
  3310 00002E25 42                  <1> 	inc	edx
  3311 00002E26 EBE3                <1> 	jmp 	short cfe2
  3312                              <1> cfe3:
  3313                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3314                              <1> 	; 02/06/2022
  3315 00002E28 FEC3                <1> 	inc	bl
  3316                              <1> 	;mov 	[month], bx
  3317 00002E2A 881D[965E0000]      <1> 	mov	[month], bl
  3318                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1	
  3319 00002E30 29D1                <1> 	sub	ecx, edx
  3320                              <1> 	;inc 	cx 			  
  3321 00002E32 FEC1                <1> 	inc	cl
  3322                              <1> 	;mov 	[day], cx
  3323 00002E34 880D[975E0000]      <1> 	mov	[day], cl    ; 02/06/2022
  3324                              <1> 	
  3325                              <1> 	; eax, ebx, ecx, edx is changed at return
  3326                              <1> 	; output ->
  3327                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3328                              <1> 
  3329                              <1> 	; 01/06/2022 (BugFix)	
  3330                              <1> _set_date:
  3331 00002E3A 66A1[945E0000]      <1> 	mov	ax, [year]
  3332 00002E40 B520                <1> 	mov	ch, 20h ; century (bcd)
  3333 00002E42 662DD007            <1> 	sub	ax, 2000
  3334 00002E46 7306                <1> 	jnc	short set_date
  3335 00002E48 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3336 00002E4A 6683C064            <1> 	add	ax, 100	
  3337                              <1> 	; 01/06/2022
  3338                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3339                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3340                              <1> set_date:
  3341                              <1>         ;mov	al, [year+1]
  3342                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3343                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3344                              <1> 	;		     ; AL = AH * 10h + AL
  3345                              <1> 	;mov 	ch, al ; century (BCD)
  3346                              <1> 	;mov 	al, [year]
  3347                              <1> 	; al = year (0-99) ; 01/06/2022
  3348 00002E4E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3349 00002E50 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3350                              <1> 			     ; AL = AH * 10h + AL
  3351 00002E52 88C1                <1> 	mov 	cl, al ; year (BCD)
  3352 00002E54 A0[965E0000]        <1>         mov 	al, [month]
  3353 00002E59 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3354 00002E5B D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3355                              <1> 			     ; AL = AH * 10h + AL
  3356 00002E5D 88C6                <1> 	mov 	dh, al ; month (BCD)
  3357 00002E5F A0[975E0000]        <1> 	mov 	al, [day]
  3358 00002E64 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3359 00002E66 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3360                              <1> 			     ; AL = AH * 10h + AL
  3361                              <1> 	; 01/06/2022 (BugFix)
  3362 00002E68 88C2                <1> 	mov 	dl, al ; day (BCD)
  3363                              <1> 
  3364                              <1> 	; Set real-time clock date
  3365 00002E6A E879000000          <1> 	call	set_rtc_date
  3366                              <1> set_time:
  3367                              <1>         ; Read real-time clock time 
  3368                              <1> 	; (get day light saving time bit status)
  3369 00002E6F FA                  <1>  	cli
  3370 00002E70 E8ABDCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3371                              <1> 	; cf = 1 -> al = 0
  3372 00002E75 7207                <1>         jc      short stime1
  3373 00002E77 B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3374 00002E79 E88CDCFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3375                              <1> stime1:
  3376 00002E7E FB                  <1> 	sti
  3377 00002E7F 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3378 00002E81 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3379                              <1> 	; DL = 1 or 0 (day light saving time)
  3380                              <1> 	;	
  3381 00002E83 A0[985E0000]        <1> 	mov 	al, [hour]
  3382 00002E88 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3383 00002E8A D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3384                              <1> 			     ; AL = AH * 10h + AL
  3385 00002E8C 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3386 00002E8E A0[995E0000]        <1>         mov     al, [minute]
  3387 00002E93 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3388 00002E95 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3389                              <1> 			     ; AL = AH * 10h + AL
  3390 00002E97 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3391 00002E99 A0[9A5E0000]        <1>         mov     al, [second]
  3392 00002E9E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3393 00002EA0 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3394                              <1> 			     ; AL = AH * 10h + AL
  3395 00002EA2 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3396                              <1> 
  3397                              <1> 	; Set real-time clock time
  3398                              <1>  	; call	set_rtc_time
  3399                              <1> set_rtc_time:
  3400                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3401                              <1> 	; 15/03/2015
  3402                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3403                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3404                              <1> 	; INT 1Ah
  3405                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3406                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3407                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3408                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3409                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3410                              <1> 	;								:
  3411                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3412                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3413                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3414                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3415                              <1> 	;
  3416                              <1> RTC_30: 				; SET RTC TIME
  3417 00002EA4 FA                  <1> 	cli
  3418 00002EA5 E876DCFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3419 00002EAA 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3420 00002EAC E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3421                              <1> RTC_35:
  3422 00002EB1 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3423 00002EB3 B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3424 00002EB5 E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3425 00002EBA 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3426 00002EBC B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3427 00002EBE E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3428 00002EC3 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3429 00002EC5 B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3430 00002EC7 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3431                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3432 00002ECC 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3433 00002ED0 E835DCFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3434 00002ED5 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3435 00002ED7 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3436 00002ED9 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3437 00002EDC 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3438 00002EDE 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3439 00002EE0 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3440 00002EE5 F8                  <1> 	CLC				; SET CY= 0
  3441 00002EE6 FB                  <1> 	sti
  3442 00002EE7 C3                  <1> 	RETn				; RETURN WITH CY= 0
  3443                              <1> 
  3444                              <1> set_rtc_date:
  3445                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3446                              <1> 	; 15/03/2015
  3447                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3448                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3449                              <1> 	; INT 1Ah
  3450                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3451                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3452                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3453                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3454                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3455                              <1> 	;
  3456                              <1> RTC_50: 				; SET RTC DATE
  3457 00002EE8 FA                  <1> 	cli
  3458 00002EE9 E832DCFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3459 00002EEE 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3460 00002EF0 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3461                              <1> RTC_55:
  3462 00002EF5 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3463 00002EF9 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3464 00002EFE 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3465 00002F00 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3466 00002F02 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3467 00002F07 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3468 00002F09 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3469 00002F0B E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3470 00002F10 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3471 00002F12 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3472 00002F14 E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3473 00002F19 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3474 00002F1B B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3475 00002F1D E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3476                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3477 00002F22 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3478 00002F26 E8DFDBFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3479 00002F2B 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3480 00002F2D 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3481 00002F2F E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3482 00002F34 F8                  <1> 	CLC				; SET CY= 0
  3483 00002F35 FB                  <1> 	sti
  3484 00002F36 C3                  <1> 	RETn				; RETURN CY=0
  3485                              <1> 
  3486                              <1> 	; 15/03/2015
  3487                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3488 00002F37 B426                <1> 	mov	ah, 26h
  3489 00002F39 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3490 00002F3B E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3491 00002F40 B482                <1> 	mov	ah, 82h
  3492 00002F42 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3493 00002F44 E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3494 00002F49 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3495 00002F4B E8BADBFFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3496 00002F50 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3497                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3498                              <1> 	;RETn
  3499                              <1> 	; 12/01/2022
  3500 00002F52 E9B3DBFFFF          <1> 	jmp	CMOS_READ
  3501                              <1> 
  3502                              <1> 	; 15/03/2015
  3503                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3504                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3505 00002F57 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3506                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3507 00002F58 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3508 00002F5A F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3509 00002F5B D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3510 00002F5D FA                  <1> 	cli			; DISABLE INTERRUPTS
  3511 00002F5E E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3512 00002F60 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3513 00002F62 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3514 00002F64 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3515 00002F66 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3516 00002F68 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3517 00002F6A 90                  <1> 	nop			; I/O DELAY
  3518 00002F6B E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3519                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3520 00002F6D 9D                  <1> 	popf	
  3521 00002F6E C3                  <1> 	RETn
  3522                              <1> 
  3523                              <1> bf_init:
  3524                              <1> 	; 14/08/2015
  3525                              <1> 	; 02/07/2015
  3526                              <1> 	; 01/07/2015
  3527                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3528                              <1> 	; Buffer (pointer) initialization !
  3529                              <1> 	; 
  3530                              <1> 	; 17/07/2013 - 24/07/2013
  3531                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3532                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3533                              <1> 	;
  3534 00002F6F BF[A8640000]        <1> 	mov	edi, bufp 
  3535 00002F74 B8[B4750000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3536 00002F79 29D2                <1> 	sub	edx, edx
  3537 00002F7B FECA                <1> 	dec	dl
  3538 00002F7D 31C9                <1> 	xor	ecx, ecx
  3539 00002F7F 49                  <1> 	dec	ecx
  3540                              <1> bi0:
  3541 00002F80 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3542 00002F85 AB                  <1> 	stosd
  3543 00002F86 89C6                <1> 	mov	esi, eax
  3544 00002F88 8916                <1> 	mov	[esi], edx ; 000000FFh
  3545                              <1> 			   ; Not a valid device sign
  3546 00002F8A 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3547                              <1> 		      ; Not a valid block number sign 	 	
  3548 00002F8D 3D[74650000]        <1> 	cmp	eax, buffer
  3549 00002F92 77EC                <1> 	ja	short bi0
  3550 00002F94 B8[B4750000]        <1> 	mov	eax, sb0
  3551 00002F99 AB                  <1> 	stosd
  3552 00002F9A B8[BC770000]        <1> 	mov	eax, sb1
  3553 00002F9F AB                  <1> 	stosd
  3554 00002FA0 89C6                <1> 	mov	esi, eax ; offset sb1
  3555 00002FA2 8916                <1> 	mov	[esi], edx ; 000000FFh
  3556                              <1> 			   ; Not a valid device sign
  3557 00002FA4 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3558                              <1> 		      ; Not a valid block number sign 	 
  3559                              <1> 	; 14/08/2015
  3560                              <1> 	;call 	rdev_init
  3561                              <1> 	;retn
  3562                              <1> 
  3563                              <1> rdev_init: ; root device, super block buffer initialization
  3564                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3565                              <1> 	; 14/08/2015
  3566                              <1> 	; Retro UNIX 386 v1 feature only !
  3567                              <1> 	;
  3568                              <1> 	; NOTE: Disk partitions (file systems), logical
  3569                              <1> 	; drive initialization, partition's start sector etc.
  3570                              <1> 	; will be coded here, later in 'ldrv_init'	
  3571                              <1> 
  3572 00002FA7 0FB605[485C0000]    <1> 	movzx	eax, byte [boot_drv]
  3573                              <1> rdi_0:
  3574 00002FAE 3C80                <1> 	cmp	al, 80h
  3575 00002FB0 7202                <1> 	jb	short rdi_1
  3576 00002FB2 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3577                              <1> rdi_1:
  3578 00002FB4 A2[D4640000]        <1> 	mov	[rdev], al
  3579 00002FB9 BB[B4750000]        <1>         mov	ebx, sb0 ; super block buffer
  3580 00002FBE 8903                <1> 	mov 	[ebx], eax
  3581 00002FC0 B001                <1> 	mov	al, 1 ; eax = 1
  3582 00002FC2 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3583                              <1> 	;call 	diskio
  3584                              <1> 	;retn
  3585                              <1> 	; 24/12/2021
  3586 00002FC5 E923250000          <1> 	jmp	diskio
  3587                              <1> 
  3588                              <1> ; 23/10/2015
  3589                              <1> com1_irq4:
  3590 00002FCA [D22F0000]          <1> 	dd	dummy_retn
  3591                              <1> com2_irq3:
  3592 00002FCE [D22F0000]          <1> 	dd	dummy_retn
  3593                              <1> 
  3594                              <1> dummy_retn:
  3595 00002FD2 C3                  <1> 	retn
  2114                                  %include 'u1.s'        ; 10/05/2015
  2115                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS1.INC
  2116                              <1> ; Last Modification: 17/07/2022
  2117                              <1> ; ----------------------------------------------------------------------------
  2118                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2119                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2120                              <1> ;
  2121                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2122                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2123                              <1> ; <Bell Laboratories (17/3/1972)>
  2124                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2125                              <1> ;
  2126                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2127                              <1> ;
  2128                              <1> ; ****************************************************************************
  2129                              <1> 
  2130                              <1> unkni: ; / used for all system calls
  2131                              <1> sysent: ; < enter to system call >
  2132                              <1> 	; 08/01/2022
  2133                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2134                              <1> 	; 19/10/2015
  2135                              <1> 	; 21/09/2015
  2136                              <1> 	; 01/07/2015
  2137                              <1> 	; 19/05/2015
  2138                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2139                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2140                              <1> 	;
  2141                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2142                              <1> 	; The trap type is determined and an indirect jump is made to 
  2143                              <1> 	; the appropriate system call handler. If there is a trap inside
  2144                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2145                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2146                              <1> 	; instructor is decoded to get the the system code part (see
  2147                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2148                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2149                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2150                              <1> 	; is called. If the call is legitimate control passes to the
  2151                              <1> 	; appropriate system routine.
  2152                              <1> 	;
  2153                              <1> 	; Calling sequence:
  2154                              <1> 	;	Through a trap caused by any sys call outside the system.
  2155                              <1> 	; Arguments:
  2156                              <1> 	;	Arguments of particular system call.	
  2157                              <1> 	; ...............................................................
  2158                              <1> 	;	
  2159                              <1> 	; Retro UNIX 8086 v1 modification: 
  2160                              <1> 	;       System call number is in EAX register.
  2161                              <1> 	;
  2162                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2163                              <1> 	;	registers depending of function details.
  2164                              <1>   	;
  2165                              <1> 	; 16/04/2015
  2166 00002FD3 368925[E4640000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2167                              <1> 	; save user registers
  2168 00002FDA 1E                  <1> 	push	ds
  2169 00002FDB 06                  <1> 	push	es
  2170 00002FDC 0FA0                <1> 	push	fs
  2171 00002FDE 0FA8                <1> 	push	gs
  2172 00002FE0 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2173                              <1> 	;
  2174                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2175                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2176                              <1> 	;	for saving/restoring user registers.)
  2177                              <1> 	;
  2178 00002FE1 50                  <1> 	push	eax ; 01/07/2015
  2179 00002FE2 66B81000            <1> 	mov     ax, KDATA
  2180 00002FE6 8ED8                <1>         mov     ds, ax
  2181 00002FE8 8EC0                <1>         mov     es, ax
  2182 00002FEA 8EE0                <1>         mov     fs, ax
  2183 00002FEC 8EE8                <1>         mov     gs, ax
  2184 00002FEE A1[28610000]        <1> 	mov	eax, [k_page_dir]
  2185 00002FF3 0F22D8              <1> 	mov	cr3, eax
  2186 00002FF6 58                  <1> 	pop	eax ; 01/07/2015
  2187                              <1> 	; 19/10/2015
  2188 00002FF7 FC                  <1> 	cld
  2189                              <1> 	;
  2190 00002FF8 FE05[E3640000]      <1> 	inc	byte [sysflg]
  2191                              <1> 		; incb sysflg / indicate a system routine is in progress
  2192 00002FFE FB                  <1>         sti 	; 18/01/2014
  2193                              <1> 	;jnz	panic ; 24/05/2013
  2194                              <1> 	; 24/12/2021
  2195 00002FFF 7405                <1> 	jz	short _1
  2196 00003001 E987F9FFFF          <1> 	jmp	panic
  2197                              <1> 		; beq 1f
  2198                              <1> 		; jmp panic ; / called if trap inside system
  2199                              <1> ;1:
  2200                              <1> _1:	; 24/12/2021
  2201                              <1> 	; 16/04/2015
  2202 00003006 A3[EC640000]        <1> 	mov	[u.r0], eax
  2203 0000300B 8925[E8640000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2204                              <1> 	;
  2205                              <1> 		; mov $s.syst+2,clockp
  2206                              <1> 		; mov r0,-(sp) / save user registers 
  2207                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2208                              <1> 			   ; / in u.r0
  2209                              <1> 		; mov r1,-(sp)
  2210                              <1> 		; mov r2,-(sp)
  2211                              <1> 		; mov r3,-(sp)
  2212                              <1> 		; mov r4,-(sp)
  2213                              <1> 		; mov r5,-(sp)
  2214                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2215                              <1> 		             ; / arithmetic unit
  2216                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2217                              <1> 		             ; / extended arithmetic unit
  2218                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2219                              <1> 		             ; / arithmetic unit
  2220                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2221                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2222                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2223                              <1> 		; sub $sys,r0 / get xxx code
  2224 00003011 C1E002              <1> 	shl	eax, 2
  2225                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2226 00003014 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2227                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2228                              <1> 	;jnb	short badsys
  2229                              <1> 		; bhis badsys / yes, bad system call
  2230                              <1> 	; 08/01/2022
  2231 00003019 7205                <1> 	jb	short _2
  2232 0000301B E95D010000          <1> 	jmp	badsys
  2233                              <1> _2:
  2234                              <1> 	; 08/01/2022
  2235                              <1> 	;cmc
  2236                              <1> 	;pushf	
  2237                              <1> 	;push	eax
  2238 00003020 8B2D[E4640000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2239                              <1> 	;mov	al, 0FEh ; 11111110b
  2240                              <1> 	;;adc	al, 0 ; al = al + cf
  2241                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2242 00003026 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2243                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2244                              <1> 				 ; / and clear carry bit
  2245                              <1> 	;pop	ebp ; eax
  2246 0000302A 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2247                              <1> 	;popf
  2248                              <1>         ;;jc	badsys
  2249                              <1> 	; 24/12/2021
  2250                              <1> 	;jnc	short _3  ; 08/01/2022
  2251                              <1> 	;jmp	badsys
  2252                              <1> ;_3:
  2253 0000302C A1[EC640000]        <1> 	mov	eax, [u.r0]
  2254                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2255 00003031 FFA5[37300000]      <1> 	jmp	dword [ebp+syscalls]
  2256                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2257                              <1> 		            ; / to proper system routine.
  2258                              <1> syscalls: ; 1:
  2259                              <1> 	; 21/09/2015
  2260                              <1> 	; 01/07/2015
  2261                              <1> 	; 16/04/2015 (32 bit address modification) 
  2262 00003037 [47310000]          <1> 	dd sysrele	; / 0
  2263 0000303B [EF310000]          <1> 	dd sysexit 	; / 1
  2264 0000303F [19330000]          <1> 	dd sysfork 	; / 2
  2265 00003043 [1F340000]          <1> 	dd sysread 	; / 3
  2266 00003047 [32340000]          <1> 	dd syswrite 	; / 4
  2267 0000304B [9B340000]          <1> 	dd sysopen 	; / 5
  2268 0000304F [C6350000]          <1> 	dd sysclose 	; / 6
  2269 00003053 [94320000]          <1> 	dd syswait 	; / 7
  2270 00003057 [43350000]          <1> 	dd syscreat 	; / 8
  2271 0000305B [7F390000]          <1> 	dd syslink 	; / 9
  2272 0000305F [3B3A0000]          <1> 	dd sysunlink 	; / 10
  2273 00003063 [053B0000]          <1> 	dd sysexec 	; / 11
  2274 00003067 [88410000]          <1> 	dd syschdir 	; / 12
  2275 0000306B [6B420000]          <1> 	dd systime 	; / 13
  2276 0000306F [7F350000]          <1> 	dd sysmkdir 	; / 14
  2277 00003073 [D8410000]          <1> 	dd syschmod 	; / 15
  2278 00003077 [3B420000]          <1> 	dd syschown 	; / 16
  2279 0000307B [9E420000]          <1> 	dd sysbreak 	; / 17
  2280 0000307F [C53E0000]          <1> 	dd sysstat 	; / 18
  2281 00003083 [6E430000]          <1> 	dd sysseek 	; / 19
  2282 00003087 [80430000]          <1> 	dd systell 	; / 20
  2283 0000308B [BE4E0000]          <1> 	dd sysmount 	; / 21
  2284 0000308F [A94F0000]          <1> 	dd sysumount 	; / 22
  2285 00003093 [FC430000]          <1> 	dd syssetuid 	; / 23
  2286 00003097 [2D440000]          <1> 	dd sysgetuid 	; / 24
  2287 0000309B [7A420000]          <1> 	dd sysstime 	; / 25
  2288 0000309F [F0430000]          <1> 	dd sysquit 	; / 26
  2289 000030A3 [E4430000]          <1> 	dd sysintr 	; / 27
  2290 000030A7 [A23E0000]          <1> 	dd sysfstat 	; / 28
  2291 000030AB [E3350000]          <1> 	dd sysemt 	; / 29
  2292 000030AF [2F360000]          <1> 	dd sysmdate 	; / 30
  2293 000030B3 [89360000]          <1> 	dd sysstty 	; / 31
  2294 000030B7 [72380000]          <1> 	dd sysgtty 	; / 32
  2295 000030BB [2A360000]          <1> 	dd sysilgins 	; / 33
  2296 000030BF [0F570000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2297                              <1> 			     ; 11/06/2014
  2298 000030C3 [26570000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2299                              <1> 			     ; 01/07/2015
  2300 000030C7 [FE570000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2301                              <1> 			     ; 21/09/2015 - get last error number
  2302                              <1> end_of_syscalls:
  2303                              <1> 
  2304                              <1> error:
  2305                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2306                              <1> 	; 17/09/2015
  2307                              <1> 	; 03/09/2015
  2308                              <1> 	; 01/09/2015
  2309                              <1> 	; 09/06/2015
  2310                              <1> 	; 13/05/2015
  2311                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2312                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2313                              <1> 	;
  2314                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2315                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2316                              <1> 	;
  2317                              <1> 	; INPUTS -> none
  2318                              <1> 	; OUTPUTS ->
  2319                              <1> 	;	processor status - carry (c) bit is set (means error)
  2320                              <1> 	;
  2321                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2322                              <1> 	; 	      Because, jumps to error procedure
  2323                              <1> 	;	      disrupts push-pop nesting balance)
  2324                              <1> 	;
  2325 000030CB 8B2D[E4640000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2326 000030D1 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2327                              <1> 				 ; (system call will return with cf = 1)
  2328                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2329                              <1> 		               ; / users stack
  2330                              <1> 	; 17/09/2015
  2331 000030D5 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2332                              <1> 				 ; for saving/restoring user registers	
  2333                              <1> 	;cmp	ebp, [u.usp]
  2334                              <1> 	;je	short err0	
  2335 000030D8 892D[E8640000]      <1> 	mov	[u.usp], ebp
  2336                              <1> ;err0:
  2337                              <1> 	; 01/09/2015
  2338 000030DE 8B25[E8640000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2339                              <1> 				    ; 10/04/2013
  2340                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2341                              <1> 				    ; related procedures will jump to 'error'
  2342                              <1> 				    ; procedure directly without returning to 
  2343                              <1> 				    ; the caller procedure. So, stack pointer
  2344                              <1>                                     ; must be restored here.)
  2345                              <1> 	; 13/05/2015
  2346                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2347                              <1> 	;	'get last error' system call later. 	
  2348                              <1> 
  2349                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2350 000030E4 C605[53650000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2351                              <1> 
  2352                              <1> sysret: ; < return from system call>
  2353                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2354                              <1> 	; 10/09/2015
  2355                              <1> 	; 29/07/2015
  2356                              <1> 	; 25/06/2015
  2357                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2358                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2359                              <1> 	;
  2360                              <1> 	; 'sysret' first checks to see if process is about to be 
  2361                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2362                              <1> 	; If not, following happens:	 
  2363                              <1> 	; 	1) The user's stack pointer is restored.
  2364                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2365                              <1> 	;	   i-node has been modified. If it has, it is written out
  2366                              <1> 	;	   via 'ppoke'.
  2367                              <1> 	;	3) If the super block has been modified, it is written out
  2368                              <1> 	;	   via 'ppoke'.				
  2369                              <1> 	;	4) If the dismountable file system's super block has been
  2370                              <1> 	;	   modified, it is written out to the specified device
  2371                              <1> 	;	   via 'ppoke'.
  2372                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2373                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2374                              <1> 	;	   another user a chance to run.
  2375                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2376                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2377                              <1> 	;
  2378                              <1> 	; Calling sequence:
  2379                              <1> 	;	jump table or 'br sysret'
  2380                              <1> 	; Arguments: 
  2381                              <1> 	;	-	
  2382                              <1> 	; ...............................................................
  2383                              <1> 	;	
  2384                              <1> 	; ((AX=r1 for 'iget' input))
  2385                              <1> 	;	
  2386                              <1> 	;xor	ax, ax ; 04/05/2013
  2387                              <1> 	; 24/12/2021
  2388 000030EB 31C0                <1> 	xor	eax, eax
  2389                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2390 000030ED FEC0                <1> 	inc	al ; 04/05/2013
  2391 000030EF 3805[3A650000]      <1> 	cmp	[u.bsys], al ; 1
  2392                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2393                              <1> 	;jnb	sysexit ; 04/05/2013
  2394                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2395                              <1> 	; 24/12/2021
  2396 000030F5 720F                <1> 	jb	short _3
  2397 000030F7 C705[41650000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2397 000030FF 0000                <1>
  2398 00003101 E9E9000000          <1> 	jmp	sysexit
  2399                              <1> _3:
  2400                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2401                              <1> 		; mov u.sp,sp / no point stack to users stack
  2402 00003106 FEC8                <1> 	dec 	al ; mov ax, 0
  2403                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2404 00003108 E8DA160000          <1> 	call	iget
  2405                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2406                              <1> 		            ; / it is written out
  2407                              <1> 	;xor 	ax, ax ; 0
  2408                              <1> 	; 24/12/2021
  2409 0000310D 31C0                <1> 	xor	eax, eax
  2410 0000310F 3805[E1640000]      <1> 	cmp	[smod], al ; 0
  2411                              <1> 		; tstb	smod / has the super block been modified
  2412 00003115 7614                <1> 	jna	short sysret1
  2413                              <1> 		; beq	1f / no, 1f
  2414 00003117 A2[E1640000]        <1> 	mov	[smod], al ; 0
  2415                              <1> 		; clrb smod / yes, clear smod
  2416 0000311C BB[B4750000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2417 00003121 66810B0002          <1>    	or	word [ebx], 200h ;;
  2418                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2419                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2420                              <1> 		      	      ; / output
  2421                              <1> 	; AX = 0
  2422 00003126 E826230000          <1> 	call 	poke ; 07/08/2013
  2423                              <1> 	; call	ppoke
  2424                              <1> 	; AX = 0
  2425                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2426                              <1> sysret1: ;1:
  2427 0000312B 3805[E2640000]      <1> 	cmp	[mmod], al ; 0
  2428                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2429                              <1> 		           ; / system
  2430 00003131 7614                <1> 	jna	short sysrel0
  2431                              <1> 		; beq 1f / been modified?  no, 1f
  2432 00003133 A2[E2640000]        <1> 	mov	[mmod], al ; 0	
  2433                              <1> 		; clrb	mmod / yes, clear mmod
  2434                              <1>         ;mov    ax, [mntd]
  2435                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2436 00003138 BB[BC770000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2437                              <1>         ;;mov	[ebx], al
  2438                              <1> 	;mov    [sb1], al
  2439                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2440 0000313D 66810B0002          <1> 	or	word [ebx], 200h
  2441                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2442                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2443 00003142 E80A230000          <1> 	call	poke ; 07/08/2013
  2444                              <1> 	;call	ppoke 
  2445                              <1> 		; jsr r0,ppoke / write it out to its device
  2446                              <1>         ;xor    al, al ; 26/04/2013       
  2447                              <1> ;1:
  2448                              <1> 		; tstb uquant / is the time quantum 0?
  2449                              <1> 		; bne 1f / no, don't swap it out
  2450                              <1> 
  2451                              <1> sysrele: ; < release >
  2452                              <1> 	; 14/10/2015
  2453                              <1> 	; 01/09/2015
  2454                              <1> 	; 24/07/2015
  2455                              <1> 	; 14/05/2015
  2456                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2457                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2458                              <1> 	;
  2459                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2460                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2461                              <1> 	; turns off the system flag. It then checked to see if there is
  2462                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2463                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2464                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2465                              <1> 	; the user, a rti is made.
  2466                              <1> 	;
  2467                              <1> 	; Calling sequence:
  2468                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2469                              <1> 	; Arguments:
  2470                              <1> 	;	-	
  2471                              <1> 	; ...............................................................
  2472                              <1> 	;	
  2473                              <1> 	; 23/02/2014 (swapret)
  2474                              <1> 	; 22/09/2013
  2475                              <1> sysrel0: ;1:
  2476 00003147 803D[2E650000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2477                              <1> 		; tstb uquant / is the time quantum 0?
  2478 0000314E 7705                <1>         ja      short swapret
  2479                              <1> 		; bne 1f / no, don't swap it out
  2480                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2481 00003150 E828130000          <1> 	call	tswap
  2482                              <1> 		; jsr r0,tswap / yes, swap it out
  2483                              <1> ;
  2484                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2485                              <1> swapret: ;1:
  2486                              <1> 	; 10/09/2015
  2487                              <1> 	; 01/09/2015
  2488                              <1> 	; 14/05/2015
  2489                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2490                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2491                              <1> 	; cli
  2492                              <1> 	; 24/07/2015
  2493                              <1> 	;
  2494                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2495                              <1> 	;; mov	esp, [u.usp]
  2496                              <1> 
  2497                              <1> 	; 22/09/2013
  2498 00003155 E8FA140000          <1> 	call	isintr
  2499                              <1> 	; 20/10/2013
  2500 0000315A 7405                <1> 	jz	short sysrel1
  2501 0000315C E877000000          <1> 	call	intract
  2502                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2503                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2504                              <1> 		               ; / action
  2505                              <1> sysrel1:
  2506 00003161 FA                  <1> 	cli ; 14/10/2015
  2507 00003162 FE0D[E3640000]      <1> 	dec	byte [sysflg]
  2508                              <1> 		; decb sysflg / turn system flag off
  2509 00003168 A1[45650000]        <1> 	mov     eax, [u.pgdir]
  2510 0000316D 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2511                              <1> 			  ; (others are different than kernel page tables) 
  2512                              <1> 	; 10/09/2015
  2513 00003170 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2514                              <1> 		; mov (sp)+,sc / restore user registers
  2515                              <1> 		; mov (sp)+,mq
  2516                              <1> 		; mov (sp)+,ac
  2517                              <1> 		; mov (sp)+,r5
  2518                              <1> 		; mov (sp)+,r4
  2519                              <1> 		; mov (sp)+,r3
  2520                              <1> 		; mov (sp)+,r2
  2521                              <1> 	;
  2522 00003171 A1[EC640000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2523 00003176 0FA9                <1> 	pop	gs
  2524 00003178 0FA1                <1> 	pop	fs
  2525 0000317A 07                  <1> 	pop	es
  2526 0000317B 1F                  <1> 	pop	ds
  2527 0000317C CF                  <1> 	iretd	
  2528                              <1> 		; rti / no, return from interrupt
  2529                              <1> 
  2530                              <1> badsys:
  2531                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2532                              <1> 	; (Major Modification: 'core' dumping procedure in
  2533                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2534                              <1> 	;	has been changed to print 'Invalid System Call !'
  2535                              <1> 	;	message on the user's console tty.)
  2536                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2537                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2538                              <1> 	; (EAX = Function number)  
  2539                              <1> 	;
  2540 0000317D FE05[3A650000]      <1> 	inc	byte [u.bsys]
  2541                              <1> 	;
  2542 00003183 8B1D[E4640000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2543 00003189 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2544 0000318B E83AE4FFFF          <1> 	call	dwordtohex
  2545 00003190 8915[885E0000]      <1> 	mov	[bsys_msg_eip], edx
  2546 00003196 A3[8C5E0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2547 0000319B A1[EC640000]        <1> 	mov	eax, [u.r0]
  2548 000031A0 E825E4FFFF          <1> 	call	dwordtohex
  2549 000031A5 8915[785E0000]      <1> 	mov	[bsys_msg_eax], edx
  2550 000031AB A3[7C5E0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2551                              <1> 	; 24/12/2021
  2552                              <1> 	;xor	eax, eax
  2553                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2554                              <1> 	;mov	ebx, [u.fofp]
  2555                              <1> 	;mov	[ebx], eax
  2556                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2557                              <1> 	;inc	eax
  2558                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2559                              <1> 		; writei
  2560                              <1> 		; INPUTS ->
  2561                              <1> 		;    r1 - inode number
  2562                              <1> 		;    u.count - byte count to be written
  2563                              <1> 		;    u.base - points to user buffer
  2564                              <1> 		;    u.fofp - points to word with current file offset
  2565                              <1> 		; OUTPUTS ->
  2566                              <1> 		;    u.count - cleared
  2567                              <1> 		;    u.nread - accumulates total bytes passed back	
  2568                              <1> 		;
  2569                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2570                              <1> 	;call	writei
  2571                              <1> 	;;mov	eax, 1
  2572                              <1> 	;jmp	sysexit
  2573                              <1> 
  2574                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2575 000031B0 BE[595E0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2576 000031B5 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2577 000031BC 8A83[43620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2578 000031C2 C605[57610000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2579 000031C9 A2[40650000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2580 000031CE E810260000          <1> 	call	print_cmsg
  2581                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2582 000031D3 E9F3FEFFFF          <1> 	jmp	error
  2583                              <1> 
  2584                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2585                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2586                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2587                              <1> 		; br 1f / error
  2588                              <1> 		; neg r1 / negate the i-number to open the core image file
  2589                              <1> 		       ; / for writing
  2590                              <1> 		; jsr r0,iopen / open the core image file
  2591                              <1> 		; jsr r0,itrunc / free all associated blocks
  2592                              <1> 		; br 2f
  2593                              <1> ;1:
  2594                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2595                              <1> 		; jsr r0,maknod / make an i-node
  2596                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2597                              <1> ;2:
  2598                              <1> 		; mov $core,u.base / move address core to u.base
  2599                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2600                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2601                              <1> 		; clr u.off / clear user offset
  2602                              <1> 		; jsr r0,writei / write out the core image to the user
  2603                              <1> 		; mov $user,u.base / pt. u.base to user
  2604                              <1> 		; mov $64.,u.count / u.count = 64
  2605                              <1> 		; jsr r0,writei / write out all the user parameters
  2606                              <1> 		; neg r1 / make i-number positive
  2607                              <1> 		; jsr r0,iclose / close the core image file
  2608                              <1> 		; br sysexit /
  2609                              <1> ;3:
  2610                              <1> 		; <core\0\0>
  2611                              <1> 
  2612                              <1> intract: ; / interrupt action
  2613                              <1> 	; 14/10/2015
  2614                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2615                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2616                              <1> 	;
  2617                              <1> 	; Retro UNIX 8086 v1 modification !
  2618                              <1> 	; (Process/task switching and quit routine by using
  2619                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2620                              <1> 	;
  2621                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2622                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2623                              <1> 	;		'intract' will jump to 'sysexit'.
  2624                              <1> 	;	    Intract will return to the caller 
  2625                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2626                              <1> 	; 14/10/2015
  2627 000031D8 FB                  <1> 	sti
  2628                              <1> 	; 07/12/2013	
  2629 000031D9 66FF05[32650000]    <1> 	inc 	word [u.quit]
  2630 000031E0 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2631 000031E2 66FF0D[32650000]    <1> 	dec	word [u.quit]
  2632                              <1> 	; 16/04/2015
  2633 000031E9 C3                  <1> 	retn
  2634                              <1> intrct0:	
  2635 000031EA 58                  <1> 	pop	eax ; call intract -> retn
  2636                              <1> 	;
  2637 000031EB 31C0                <1> 	xor 	eax, eax
  2638 000031ED FEC0                <1> 	inc	al  ; mov ax, 1
  2639                              <1> ;;;
  2640                              <1> 	; UNIX v1 original 'intract' routine... 
  2641                              <1> 	; / interrupt action
  2642                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2643                              <1> 		; bne 1f / no, 1f
  2644                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2645                              <1> 	; 1: / now in user area
  2646                              <1> 		; mov r1,-(sp) / save r1
  2647                              <1> 		; mov u.ttyp,r1 
  2648                              <1> 			; / pointer to tty buffer in control-to r1
  2649                              <1> 		; cmpb 6(r1),$177
  2650                              <1> 			; / is the interrupt char equal to "del"
  2651                              <1> 		; beq 1f / yes, 1f
  2652                              <1> 		; clrb 6(r1) 
  2653                              <1> 		        ; / no, clear the byte 
  2654                              <1> 			; / (must be a quit character)
  2655                              <1> 		; mov (sp)+,r1 / restore r1
  2656                              <1> 		; clr u.quit / clear quit flag
  2657                              <1> 		; bis $20,2(sp) 
  2658                              <1> 		    	; / set trace for quit (sets t bit of 
  2659                              <1> 			; / ps-trace trap)
  2660                              <1> 		; rti   ;  / return from interrupt
  2661                              <1> 	; 1: / interrupt char = del
  2662                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2663                              <1> 			   ; / in the buffer
  2664                              <1> 		; mov (sp)+,r1 / restore r1
  2665                              <1> 		; cmp u.intr,$core / should control be 
  2666                              <1> 				; / transferred to loc core?
  2667                              <1> 		; blo 1f
  2668                              <1> 		; jmp *u.intr / user to do rti yes, 
  2669                              <1> 				; / transfer to loc core
  2670                              <1> 	; 1:
  2671                              <1> 		; sys 1 / exit
  2672                              <1> 
  2673                              <1> sysexit: ; <terminate process>
  2674                              <1> 	; 17/07/2022
  2675                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2676                              <1> 	; 01/09/2015
  2677                              <1> 	; 31/08/2015
  2678                              <1> 	; 14/05/2015
  2679                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2680                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2681                              <1> 	;
  2682                              <1> 	; 'sysexit' terminates a process. First each file that
  2683                              <1> 	; the process has opened is closed by 'flose'. The process
  2684                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2685                              <1> 	; searched to find children of the dying process. If any of
  2686                              <1> 	; children are zombies (died by not waited for), they are
  2687                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2688                              <1> 	; dying process's parent. When the parent is found, it is
  2689                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2690                              <1> 	; one of these, the dying process just dies. If it is waiting
  2691                              <1> 	; for a child process to die, it notified that it doesn't 
  2692                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2693                              <1> 	; (waiting to active). It is awakened and put on runq by
  2694                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2695                              <1> 	; it will never be run again but stays around until a 'wait'
  2696                              <1> 	; is completed by it's parent process. If the parent is not
  2697                              <1> 	; found, process just dies. This means 'swap' is called with
  2698                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2699                              <1> 	; to write out the process and 'rswap' reads the new process
  2700                              <1> 	; over the one that dies..i.e., the dying process is 
  2701                              <1> 	; overwritten and destroyed.	
  2702                              <1>  	;
  2703                              <1> 	; Calling sequence:
  2704                              <1> 	;	sysexit or conditional branch.
  2705                              <1> 	; Arguments:
  2706                              <1> 	;	-	
  2707                              <1> 	; ...............................................................
  2708                              <1> 	;	
  2709                              <1> 	; Retro UNIX 8086 v1 modification: 
  2710                              <1> 	;       System call number (=1) is in EAX register.
  2711                              <1> 	;
  2712                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2713                              <1> 	;       registers depending of function details.
  2714                              <1> 	;
  2715                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2716                              <1> 	;
  2717                              <1> ; / terminate process
  2718                              <1> 	; AX = 1
  2719                              <1> 	;dec 	ax ; 0
  2720                              <1> 	; 24/12/2021
  2721 000031EF 48                  <1> 	dec	eax ; 0
  2722                              <1> 	;dec 	ax ; 0
  2723 000031F0 66A3[30650000]      <1> 	mov	[u.intr], ax ; 0
  2724                              <1> 		; clr u.intr / clear interrupt control word
  2725                              <1> 		; clr r1 / clear r1
  2726                              <1> 	; AX = 0
  2727                              <1> sysexit_1: ; 1:
  2728                              <1> 	; AX = File descriptor
  2729                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2730                              <1> 		; / Search the whole list
  2731 000031F6 E8680D0000          <1> 	call	fclose
  2732                              <1> 		; jsr r0,fclose / close all files the process opened
  2733                              <1> 	;; ignore error return
  2734                              <1> 		; br .+2 / ignore error return
  2735                              <1> 	;inc	ax
  2736 000031FB FEC0                <1> 	inc	al
  2737                              <1> 		; inc r1 / increment file descriptor
  2738                              <1> 	;cmp	ax, 10
  2739 000031FD 3C0A                <1> 	cmp	al, 10
  2740                              <1> 		; cmp r1,$10. / end of u.fp list?
  2741 000031FF 72F5                <1> 	jb	short sysexit_1
  2742                              <1> 		; blt 1b / no, go back
  2743 00003201 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2744                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2745 00003208 88A3[63620000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2746                              <1> 		; clrb p.stat-1(r1) / free the process
  2747                              <1> 	;shl	bx, 1
  2748 0000320E D0E3                <1> 	shl	bl, 1
  2749                              <1> 		; asl r1 / use r1 for index into the below tables
  2750 00003210 668B8B[02620000]    <1> 	mov	cx, [ebx+p.pid-2]
  2751                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2752 00003217 668B93[22620000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2753                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2754                              <1> 	; xor 	bx, bx ; 0
  2755 0000321E 30DB                <1> 	xor	bl, bl ; 0
  2756                              <1> 		; clr r2
  2757 00003220 31F6                <1> 	xor	esi, esi ; 0
  2758                              <1> 		; clr r5 / initialize reg
  2759                              <1> sysexit_2: ; 1:
  2760                              <1> 	        ; / find children of this dying process, 
  2761                              <1> 		; / if they are zombies, free them
  2762                              <1> 	;add	bx, 2
  2763 00003222 80C302              <1> 	add	bl, 2
  2764                              <1> 		; add $2,r2 / search parent process table 
  2765                              <1> 		          ; / for dying process's name
  2766 00003225 66398B[22620000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2767                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2768 0000322C 7513                <1> 	jne	short sysexit_4
  2769                              <1> 		; bne 3f / no
  2770                              <1> 	;shr	bx, 1
  2771 0000322E D0EB                <1> 	shr	bl, 1
  2772                              <1> 		; asr r2 / yes, it is a parent
  2773 00003230 80BB[63620000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2774                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2775                              <1> 				     ; / dying process a zombie
  2776 00003237 7506                <1> 	jne	short sysexit_3 
  2777                              <1> 		; bne 2f / no
  2778 00003239 88A3[63620000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2779                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2780                              <1> sysexit_3: ; 2:
  2781                              <1> 	;shr	bx, 1
  2782 0000323F D0E3                <1> 	shl	bl, 1
  2783                              <1> 		; asl r2
  2784                              <1> sysexit_4: ; 3:
  2785                              <1> 		; / search the process name table 
  2786                              <1> 		; / for the dying process's parent
  2787 00003241 663993[02620000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2788                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2789 00003248 7502                <1> 	jne	short sysexit_5
  2790                              <1> 		; bne 3f / no
  2791 0000324A 89DE                <1> 	mov	esi, ebx
  2792                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2793                              <1> 		          ; / process # x2) in r5
  2794                              <1> sysexit_5: ; 3:
  2795                              <1> 	;cmp	bx, nproc + nproc
  2796 0000324C 80FB20              <1> 	cmp	bl, nproc + nproc
  2797                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2798 0000324F 72D1                <1> 	jb	short sysexit_2
  2799                              <1> 		; blt 1b / no, go back
  2800                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2801 00003251 21F6                <1> 	and	esi, esi ; r5=r1
  2802 00003253 7430                <1> 	jz	short sysexit_6
  2803                              <1> 		; beq 2f / no parent has been found. 
  2804                              <1> 		       ; / The process just dies
  2805                              <1> 	;shr	si, 1
  2806                              <1> 	; 17/07/2022
  2807 00003255 D1EE                <1> 	shr	esi, 1
  2808                              <1> 		; asr r1 / set up index to p.stat
  2809 00003257 8A86[63620000]      <1> 	mov	al, [esi+p.stat-1]
  2810                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2811 0000325D 20C0                <1> 	and	al, al
  2812 0000325F 7424                <1> 	jz	short sysexit_6
  2813                              <1> 		; beq 2f / if its been freed, 2f
  2814 00003261 3C03                <1> 	cmp	al, 3
  2815                              <1> 		; cmp r2,$3 / is parent a zombie?
  2816 00003263 7420                <1> 	je	short sysexit_6
  2817                              <1> 		; beq 2f / yes, 2f
  2818                              <1> 	; BH = 0
  2819 00003265 8A1D[3B650000]      <1> 	mov	bl, [u.uno]
  2820                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2821 0000326B C683[63620000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2822                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2823                              <1> 	; 05/02/2014
  2824 00003272 3C01                <1> 	cmp	al, 1 ; SRUN
  2825 00003274 740F                <1> 	je	short sysexit_6
  2826                              <1> 	;cmp	al, 2
  2827                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2828                              <1> 			  ; / this child to die
  2829                              <1> 	;jne	short sysexit_6	
  2830                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2831                              <1> 	; 05/02/2014
  2832                              <1> 	; p.stat = 2 --> waiting
  2833                              <1> 	; p.stat = 4 --> sleeping
  2834 00003276 C686[63620000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2835                              <1> 	;dec	byte [esi+p.stat-1]
  2836                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2837 0000327D 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2838                              <1> 	; 
  2839                              <1> 	;mov	ebx, runq + 4
  2840                              <1> 		; mov $runq+4,r2 / on the runq
  2841 00003280 E8CF120000          <1> 	call	putlu
  2842                              <1> 		; jsr r0, putlu
  2843                              <1> sysexit_6: ; 2:
  2844                              <1> 	; 31/08/2015
  2845                              <1> 		; / the process dies
  2846 00003285 C605[3B650000]00    <1> 	mov	byte [u.uno], 0
  2847                              <1> 		; clrb u.uno / put zero as the process number, 
  2848                              <1> 	           ; / so "swap" will
  2849 0000328C E8F6110000          <1> 	call	swap
  2850                              <1> 		; jsr r0,swap / overwrite process with another process
  2851                              <1> hlt_sys:
  2852                              <1> 	;sti ; 18/01/2014
  2853                              <1> hlts0:
  2854 00003291 F4                  <1> 	hlt
  2855 00003292 EBFD                <1> 	jmp	short hlts0
  2856                              <1> 		; 0 / and thereby kill it; halt?
  2857                              <1> 
  2858                              <1> 
  2859                              <1> syswait: ; < wait for a processs to die >
  2860                              <1> 	; 09/02/2022
  2861                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2862                              <1> 	; 17/09/2015
  2863                              <1> 	; 02/09/2015
  2864                              <1> 	; 01/09/2015
  2865                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2866                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2867                              <1> 	;
  2868                              <1> 	; 'syswait' waits for a process die. 
  2869                              <1> 	; It works in following way:
  2870                              <1> 	;    1) From the parent process number, the parent's 
  2871                              <1> 	; 	process name is found. The p.ppid table of parent
  2872                              <1> 	;	names is then searched for this process name.
  2873                              <1> 	;	If a match occurs, r2 contains child's process
  2874                              <1> 	;	number. The child status is checked to see if it is
  2875                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2876                              <1> 	;	If it is, the child process is freed and it's name
  2877                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2878                              <1> 	;	If the child is not a zombie, nothing happens and
  2879                              <1> 	;	the search goes on through the p.ppid table until
  2880                              <1> 	;	all processes are checked or a zombie is found.
  2881                              <1> 	;    2) If no zombies are found, a check is made to see if
  2882                              <1> 	;	there are any children at all. If there are none,
  2883                              <1> 	;	an error return is made. If there are, the parent's
  2884                              <1> 	;	status is set to 2 (waiting for child to die),
  2885                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2886                              <1> 	;	is made to wait on the next process.
  2887                              <1> 	;
  2888                              <1> 	; Calling sequence:
  2889                              <1> 	;	?
  2890                              <1> 	; Arguments:
  2891                              <1> 	;	-
  2892                              <1> 	; Inputs: - 
  2893                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2894                              <1> 	; ...............................................................
  2895                              <1> 	;				
  2896                              <1> 	
  2897                              <1> ; / wait for a process to die
  2898                              <1> 
  2899                              <1> syswait_0:
  2900 00003294 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2901                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2902 0000329B D0E3                <1> 	shl	bl, 1
  2903                              <1> 	;shl	bx, 1
  2904                              <1> 		; asl r1 / x2 to get index into p.pid table
  2905 0000329D 668B83[02620000]    <1> 	mov	ax, [ebx+p.pid-2]
  2906                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2907 000032A4 31F6                <1> 	xor	esi, esi
  2908                              <1> 		; clr r2
  2909 000032A6 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2910                              <1> 	;xor 	cl, cl
  2911                              <1> 		; clr r3 / initialize reg 3
  2912                              <1> syswait_1: ; 1:
  2913                              <1> 	; 09/02/2022
  2914 000032A8 46                  <1> 	inc	esi
  2915 000032A9 46                  <1> 	inc	esi
  2916                              <1> 	;add	si, 2
  2917                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2918                              <1> 			  ; / search table of parent processes 
  2919                              <1> 			  ; / for this process name
  2920 000032AA 663B86[22620000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2921                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2922                              <1> 			            ; / process number
  2923 000032B1 7531                <1> 	jne	short syswait_3
  2924                              <1> 		;bne 3f / branch if no match of parent process name
  2925                              <1> 	;inc	cx
  2926 000032B3 FEC1                <1> 	inc	cl
  2927                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2928                              <1> 	; 09/02/2022
  2929 000032B5 D1EE                <1> 	shr	esi, 1
  2930                              <1> 	;shr	si, 1
  2931                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2932                              <1> 	; The possible states ('p.stat' values) of a process are:
  2933                              <1> 	;	0 = free or unused
  2934                              <1> 	;	1 = active
  2935                              <1> 	;	2 = waiting for a child process to die
  2936                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2937 000032B7 80BE[63620000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2938                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2939 000032BE 7522                <1> 	jne	short syswait_2
  2940                              <1> 		; bne 2f / no, skip it
  2941 000032C0 88BE[63620000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2942                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2943                              <1> 	; 09/02/2022
  2944 000032C6 D1E6                <1> 	shl	esi, 1
  2945                              <1> 	;shl	si, 1
  2946                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2947 000032C8 0FB786[02620000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2948 000032CF A3[EC640000]        <1> 	mov	[u.r0], eax
  2949                              <1> 		; mov p.pid-2(r2),*u.r0 
  2950                              <1> 			      ; / put childs process name in (u.r0)
  2951                              <1> 	;
  2952                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2953                              <1> 	;
  2954                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2955                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2956                              <1> 	; system call loop from the application/program if it calls
  2957                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2958                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2959                              <1> 	;
  2960                              <1> 	; Note: syswait will return with error if there is not a
  2961                              <1> 	;       zombie or running process to wait.	
  2962                              <1> 	;
  2963                              <1> 	;sub	ax, ax
  2964                              <1> 	; 08/01/2022
  2965 000032D4 29C0                <1> 	sub	eax, eax
  2966 000032D6 668986[22620000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2967 000032DD E90BFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2968                              <1> 	;
  2969                              <1> 	;jmp	sysret
  2970                              <1> 		; br sysret1 / return cause child is dead
  2971                              <1> syswait_2: ; 2:
  2972                              <1> 	; 09/02/2022
  2973 000032E2 D1E6                <1> 	shl	esi, 1
  2974                              <1> 	;shl	si, 1
  2975                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2976                              <1> syswait_3: ; 3:
  2977 000032E4 6683FE20            <1> 	cmp	si, nproc+nproc
  2978                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2979 000032E8 72BE                <1> 	jb	short syswait_1
  2980                              <1> 		; blt 1b / no, continue search
  2981                              <1> 	;and	cx, cx
  2982 000032EA 20C9                <1> 	and	cl, cl
  2983                              <1> 		; tst r3 / one gets here if there are no children 
  2984                              <1> 		       ; / or children that are still active
  2985                              <1> 	; 30/10/2013
  2986 000032EC 7515                <1> 	jnz	short syswait_4
  2987                              <1> 	;jz	error
  2988                              <1> 		; beq error1 / there are no children, error
  2989 000032EE 890D[EC640000]      <1> 	mov	[u.r0], ecx ; 0
  2990                              <1> 	; 09/02/2022
  2991 000032F4 C705[41650000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2991 000032FC 0000                <1>
  2992                              <1> 			; miscellaneous/other errors
  2993 000032FE E9C8FDFFFF          <1> 	jmp	error
  2994                              <1> syswait_4:
  2995 00003303 8A1D[3B650000]      <1> 	mov	bl, [u.uno]
  2996                              <1> 		; movb u.uno,r1 / there are children so put 
  2997                              <1> 			      ; / parent process number in r1
  2998 00003309 FE83[63620000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2999                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  3000                              <1> 				  ; / other children to die
  3001                              <1> 	; 04/11/2013
  3002 0000330F E873110000          <1> 	call	swap
  3003                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  3004 00003314 E97BFFFFFF          <1> 	jmp	syswait_0
  3005                              <1> 		; br syswait / wait on next process
  3006                              <1> 
  3007                              <1> sysfork: ; < create a new process >
  3008                              <1> 	; 26/02/2022
  3009                              <1> 	; 25/02/2022
  3010                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  3011                              <1> 	; 18/09/2015
  3012                              <1> 	; 04/09/2015
  3013                              <1> 	; 02/09/2015
  3014                              <1> 	; 01/09/2015
  3015                              <1> 	; 28/08/2015
  3016                              <1> 	; 14/05/2015
  3017                              <1> 	; 10/05/2015
  3018                              <1> 	; 09/05/2015
  3019                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3020                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3021                              <1> 	;
  3022                              <1> 	; 'sysfork' creates a new process. This process is referred
  3023                              <1> 	; to as the child process. This new process core image is
  3024                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3025                              <1> 	; distinction is the return location and the fact that (u.r0)
  3026                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3027                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3028                              <1> 	; 'sysfork' works in the following manner: 	
  3029                              <1> 	;    1) The process status table (p.stat) is searched to find
  3030                              <1> 	;	a process number that is unused. If none are found
  3031                              <1> 	;	an error occurs.
  3032                              <1> 	;    2) when one is found, it becomes the child process number
  3033                              <1> 	;	and it's status (p.stat) is set to active.
  3034                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3035                              <1> 	;	character in that tty buffer is cleared.
  3036                              <1> 	;    4) The child process is put on the lowest priority run 
  3037                              <1> 	;	queue via 'putlu'.
  3038                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3039                              <1> 	;	it is a unique number) and is put in the child's unique
  3040                              <1> 	;	identifier; process id (p.pid).
  3041                              <1> 	;    6) The process name of the parent is then obtained and
  3042                              <1> 	;	placed in the unique identifier of the parent process
  3043                              <1> 	;	name is then put in 'u.r0'.	
  3044                              <1> 	;    7) The child process is then written out on disk by
  3045                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3046                              <1> 	;	and the child is born. (The child process is written 
  3047                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3048                              <1> 	;	number.)
  3049                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3050                              <1> 	;    9) The child process name is put in 'u.r0'.
  3051                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3052                              <1> 	;	create the return address for the parent process.
  3053                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3054                              <1> 	;	the parent has opened. For each file the parent has
  3055                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3056                              <1> 	;	to indicate that the child process also has opened
  3057                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3058                              <1> 	;
  3059                              <1> 	; Calling sequence:
  3060                              <1> 	;	from shell ?
  3061                              <1> 	; Arguments:
  3062                              <1> 	;	-
  3063                              <1> 	; Inputs: -
  3064                              <1> 	; Outputs: *u.r0 - child process name
  3065                              <1> 	; ...............................................................
  3066                              <1> 	;	
  3067                              <1> 	; Retro UNIX 8086 v1 modification: 
  3068                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3069                              <1> 	;	= process id of child a parent process returns
  3070                              <1> 	;	= process id of parent when a child process returns
  3071                              <1> 	;
  3072                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3073                              <1> 	;	in following manner: (with an example: c library, fork)
  3074                              <1> 	;	
  3075                              <1> 	;	1:
  3076                              <1> 	;		sys	fork
  3077                              <1> 	;			br 1f  / child process returns here
  3078                              <1> 	;		bes	2f     / parent process returns here
  3079                              <1> 	;		/ pid of new process in r0
  3080                              <1> 	;		rts	pc
  3081                              <1> 	;	2: / parent process condionally branches here
  3082                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3083                              <1> 	;		rts	pc
  3084                              <1> 	;
  3085                              <1> 	;	1: / child process brances here
  3086                              <1> 	;		clr	r0   / pid = 0 in child process
  3087                              <1> 	;		rts	pc
  3088                              <1> 	;
  3089                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3090                              <1> 	;		// pid = fork();
  3091                              <1> 	;		//
  3092                              <1> 	;		// pid == 0 in child process; 
  3093                              <1> 	;		// pid == -1 means error return
  3094                              <1> 	;		// in child, 
  3095                              <1> 	;		//	parents id is in par_uid if needed
  3096                              <1> 	;		
  3097                              <1> 	;		_fork:
  3098                              <1> 	;			mov	$.fork,eax
  3099                              <1> 	;			int	$0x30
  3100                              <1> 	;			jmp	1f
  3101                              <1> 	;			jnc	2f
  3102                              <1> 	;			jmp	cerror
  3103                              <1> 	;		1:
  3104                              <1> 	;			mov	eax,_par_uid
  3105                              <1> 	;			xor	eax,eax
  3106                              <1> 	;		2:
  3107                              <1> 	;			ret
  3108                              <1> 	;
  3109                              <1> 	;	In Retro UNIX 8086 v1,
  3110                              <1> 	;	'sysfork' returns in following manner:
  3111                              <1> 	;	
  3112                              <1> 	;		mov	ax, sys_fork
  3113                              <1> 	;		mov	bx, offset @f ; routine for child
  3114                              <1> 	;		int	20h
  3115                              <1> 	;		jc	error
  3116                              <1> 	;		
  3117                              <1> 	;	; Routine for parent process here (just after 'jc')
  3118                              <1> 	;		mov	word ptr [pid_of_child], ax
  3119                              <1> 	;		jmp	next_routine_for_parent	
  3120                              <1> 	;
  3121                              <1> 	;	@@: ; routine for child process here				
  3122                              <1> 	;		....	
  3123                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3124                              <1> 	;	       for child process by using BX input.
  3125                              <1> 	;	      (at first, parent process will return then 
  3126                              <1> 	;	      child process will return -after swapped in-
  3127                              <1> 	;	      'syswait' is needed in parent process
  3128                              <1> 	;	      if return from child process will be waited for.)
  3129                              <1> 	;	  				
  3130                              <1> 	
  3131                              <1> ; / create a new process
  3132                              <1> 	; EBX = return address for child process 
  3133                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3134 00003319 31F6                <1> 	xor 	esi, esi
  3135                              <1> 		; clr r1
  3136                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3137 0000331B 46                  <1> 	inc	esi
  3138                              <1> 		; inc r1
  3139 0000331C 80BE[63620000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3140                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3141 00003323 760B                <1> 	jna	short sysfork_2	
  3142                              <1> 		; beq 1f / it's unused so branch
  3143 00003325 6683FE10            <1> 	cmp	si, nproc
  3144                              <1> 		; cmp r1,$nproc / all processes checked
  3145 00003329 72F0                <1> 	jb	short sysfork_1
  3146                              <1> 		; blt 1b / no, branch back
  3147                              <1> 	;
  3148                              <1> 	; Retro UNIX 8086 v1. modification:
  3149                              <1> 	;	Parent process returns from 'sysfork' to address 
  3150                              <1> 	;	which is just after 'sysfork' system call in parent
  3151                              <1> 	;	process. Child process returns to address which is put
  3152                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3153                              <1> 	;
  3154                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3155                              <1> 		             ; / to old process return
  3156                              <1> 		; br error1 / no room for a new process
  3157                              <1> sysfork_0:
  3158 0000332B E99BFDFFFF          <1> 	jmp	error
  3159                              <1> sysfork_2: ; 1:
  3160 00003330 E88CF0FFFF          <1> 	call	allocate_page
  3161                              <1> 	;jc	error
  3162                              <1> 	; 08/01/2022
  3163 00003335 72F4                <1> 	jc	short sysfork_0
  3164                              <1> 
  3165 00003337 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3166                              <1> 	; Retro UNIX 386 v1 modification!
  3167 00003338 E87BF2FFFF          <1> 	call	duplicate_page_dir
  3168                              <1> 		; EAX = New page directory 
  3169 0000333D 7308                <1> 	jnc	short sysfork_3
  3170 0000333F 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3171 00003340 E842F2FFFF          <1> 	call 	deallocate_page
  3172                              <1> 	;jmp	error
  3173                              <1> 	; 08/01/2022
  3174 00003345 EBE4                <1> 	jmp	short sysfork_0 ; error
  3175                              <1> sysfork_3:
  3176                              <1> 	; Retro UNIX 386 v1 modification !
  3177 00003347 56                  <1> 	push	esi
  3178 00003348 E8B1110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3179                              <1> 		      ; and interrupt return components (for IRET)
  3180 0000334D 8705[45650000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3181 00003353 A3[49650000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3182 00003358 5E                  <1> 	pop	esi
  3183 00003359 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3184                              <1> 		; [u.usp] = esp
  3185 0000335A 89F7                <1> 	mov	edi, esi
  3186                              <1> 	;shl	di, 2
  3187                              <1> 	; 08/01/2022
  3188 0000335C C1E702              <1> 	shl	edi, 2
  3189 0000335F 8987[70620000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3190 00003365 A3[3C650000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3191                              <1> 	; 28/08/2015
  3192 0000336A 0FB605[3B650000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3193                              <1> 		; movb u.uno,-(sp) / save parent process number
  3194 00003371 89C7                <1> 	mov	edi, eax
  3195 00003373 50                  <1>         push	eax ; ** 
  3196 00003374 8A87[43620000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3197                              <1> 		; 18/09/2015
  3198 0000337A 8886[43620000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3199                              <1> 	; 26/02/2022 (p.waitc is not used)
  3200                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3201                              <1> 	; 25/02/2022 (BugFix)
  3202                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3203                              <1> 	;			   ; ah - reset child's wait channel	
  3204 00003380 89F0                <1> 	mov	eax, esi
  3205 00003382 A2[3B650000]        <1> 	mov	[u.uno], al ; child process number
  3206                              <1> 		;movb r1,u.uno / set child process number to r1
  3207 00003387 FE86[63620000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3208                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3209                              <1> 				; / process to active status
  3210                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3211                              <1> 			      ; / control tty buffer in r2
  3212                              <1>                 ; beq 2f / branch, if no such tty assigned
  3213                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3214                              <1> 	; 2:
  3215 0000338D 53                  <1> 	push	ebx  ; * return address for the child process
  3216                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3217                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3218                              <1> 		; mov $runq+4,r2
  3219 0000338E E8C1110000          <1> 	call	putlu 
  3220                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3221                              <1> 			   ; / run queue
  3222                              <1> 	; 08/01/2022
  3223 00003393 D1E6                <1> 	shl	esi, 1
  3224                              <1> 	;shl	si, 1
  3225                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3226                              <1> 		       ; / into p.pid table
  3227 00003395 66FF05[DA640000]    <1> 	inc	word [mpid]
  3228                              <1> 		; inc mpid / increment m.pid; get a new process name
  3229 0000339C 66A1[DA640000]      <1> 	mov	ax, [mpid]
  3230 000033A2 668986[02620000]    <1> 	mov	[esi+p.pid-2], ax
  3231                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3232                              <1> 				    ; / in child process' name slot
  3233 000033A9 5A                  <1> 	pop	edx  ; * return address for the child process
  3234                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3235 000033AA 5B                  <1>   	pop	ebx  ; **
  3236                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3237                              <1> 		; movb (sp),r2 / put parent process number in r2
  3238                              <1> 	; 08/01/2022
  3239 000033AB D1E3                <1> 	shl	ebx, 1
  3240                              <1> 	;shl 	bx, 1
  3241                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3242                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3243 000033AD 668B83[02620000]    <1> 	mov	ax, [ebx+p.pid-2]
  3244                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3245                              <1> 				   ; / process
  3246 000033B4 668986[22620000]    <1> 	mov	[esi+p.ppid-2], ax
  3247                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3248                              <1> 			  ; / in parent process slot for child
  3249 000033BB A3[EC640000]        <1> 	mov	[u.r0], eax	
  3250                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3251                              <1> 			     ; / at location where r0 was saved
  3252 000033C0 8B2D[E4640000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3253 000033C6 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3254                              <1> 			   ; * return address for the child process
  3255                              <1> 		; mov $sysret1,-(sp) /
  3256                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3257                              <1> 			      ; / user is swapped out
  3258                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3259                              <1> 	; 04/09/2015 - 01/09/2015
  3260                              <1> 	; [u.usp] = esp
  3261 000033C9 68[EB300000]        <1> 	push	sysret ; ***
  3262 000033CE 8925[E8640000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3263                              <1> 			     ; (for child process)	
  3264 000033D4 31C0                <1> 	xor 	eax, eax
  3265 000033D6 66A3[1C650000]      <1> 	mov 	[u.ttyp], ax ; 0
  3266                              <1> 	;
  3267 000033DC E81D110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3268                              <1> 		;jsr r0,wswap / put child process out on drum
  3269                              <1> 		;jsr r0,unpack / unpack user stack
  3270                              <1> 		;mov u.usp,sp / restore user stack pointer
  3271                              <1> 		; tst (sp)+ / bump stack pointer
  3272                              <1> 	; Retro UNIX 386 v1 modification !
  3273 000033E1 58                  <1> 	pop	eax ; ***
  3274                              <1> 	; 08/01/2022
  3275 000033E2 D1E3                <1> 	shl	ebx, 1
  3276                              <1> 	;shl 	bx, 1
  3277 000033E4 8B83[70620000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3278 000033EA E838110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3279                              <1> 		      ; registers and return address (for IRET)
  3280                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3281 000033EF 0FB705[DA640000]    <1>         movzx   eax, word [mpid]
  3282 000033F6 A3[EC640000]        <1> 	mov	[u.r0], eax
  3283                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3284                              <1> 			       ; / where r0 was saved
  3285                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3286                              <1> 			          ; / process return
  3287                              <1> 	;xor	ebx, ebx
  3288 000033FB 31F6                <1> 	xor     esi, esi
  3289                              <1> 		;clr r1
  3290                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3291                              <1> 	      ; / opened by the parent process
  3292                              <1> 	; 01/09/2015
  3293                              <1> 	;xor	bh, bh
  3294                              <1> 	;mov 	bl, [esi+u.fp]
  3295 000033FD 8A86[F2640000]      <1> 	mov 	al, [esi+u.fp]
  3296                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3297                              <1>         ;or	bl, bl
  3298 00003403 08C0                <1> 	or	al, al
  3299 00003405 740C                <1> 	jz	short sysfork_5	
  3300                              <1> 		; beq 2f / file has not been opened by parent, 
  3301                              <1> 		       ; / so branch
  3302 00003407 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3303 00003409 F6E4                <1> 	mul	ah
  3304                              <1> 	;;movzx	ebx, ax
  3305                              <1> 	;mov	bx, ax
  3306 0000340B 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3307                              <1> 	;shl	bx, 3
  3308                              <1> 		; asl r2 / multiply by 8
  3309                              <1>        		; asl r2 / to get index into fsp table
  3310                              <1>        		; asl r2
  3311 0000340D FE83[B2620000]      <1>   	inc     byte [ebx+fsp-2]
  3312                              <1> 		; incb fsp-2(r2) / increment number of processes
  3313                              <1> 			     ; / using file, because child will now be
  3314                              <1> 			     ; / using this file
  3315                              <1> sysfork_5: ; 2:
  3316 00003413 46                  <1>         inc     esi
  3317                              <1> 		; inc r1 / get next open file
  3318 00003414 6683FE0A            <1>         cmp     si, 10
  3319                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3320                              <1> 			  ; / can be opened
  3321 00003418 72E3                <1> 	jb	short sysfork_4	
  3322                              <1> 		; blt 1b / check next entry
  3323 0000341A E9CCFCFFFF          <1> 	jmp	sysret
  3324                              <1> 		; br sysret1
  3325                              <1> 
  3326                              <1> sysread: ; < read from file >
  3327                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3328                              <1> 	; 13/05/2015
  3329                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3330                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3331                              <1> 	;
  3332                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3333                              <1> 	; characters to be read. If finds the file from the file
  3334                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3335                              <1> 	; is returned from a successful open call (sysopen).
  3336                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3337                              <1> 	; is read into core via 'readi'.
  3338                              <1> 	;
  3339                              <1> 	; Calling sequence:
  3340                              <1> 	;	sysread; buffer; nchars
  3341                              <1> 	; Arguments:
  3342                              <1> 	;	buffer - location of contiguous bytes where 
  3343                              <1> 	;		 input will be placed.
  3344                              <1> 	;	nchars - number of bytes or characters to be read.
  3345                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3346                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3347                              <1> 	; ...............................................................
  3348                              <1> 	;				
  3349                              <1> 	; Retro UNIX 8086 v1 modification: 
  3350                              <1> 	;       'sysread' system call has three arguments; so,
  3351                              <1> 	;	* 1st argument, file descriptor is in BX register
  3352                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3353                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3354                              <1> 	;
  3355                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3356                              <1> 	;	to the user with number of bytes read. 
  3357                              <1> 	;
  3358 0000341F E840000000          <1> 	call	rw1
  3359                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3360                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3361                              <1>        	; 24/12/2021
  3362 00003424 7239                <1> 	jc	short sysread_err
  3363 00003426 F6C480              <1> 	test	ah, 80h
  3364                              <1> 		; tst r1 / negative i-number?
  3365 00003429 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3366                              <1> 	;jnz	error
  3367                              <1> 		; ble error1 / yes, error 1 to read
  3368                              <1> 			   ; / it should be positive
  3369 0000342B E88B150000          <1> 	call	readi
  3370                              <1> 		; jsr r0,readi / read data into core
  3371 00003430 EB14                <1> 	jmp	short rw0
  3372                              <1> 		; br 1f
  3373                              <1> 
  3374                              <1> syswrite: ; < write to file >
  3375                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3376                              <1> 	; 13/05/2015
  3377                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3378                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3379                              <1> 	;
  3380                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3381                              <1> 	; and the number of characters to write. If finds the file
  3382                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3383                              <1> 	; descriptor is returned from a successful open or create call
  3384                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3385                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3386                              <1> 	;
  3387                              <1> 	; Calling sequence:
  3388                              <1> 	;	syswrite; buffer; nchars
  3389                              <1> 	; Arguments:
  3390                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3391                              <1> 	;	nchars - number of characters to be written.
  3392                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3393                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3394                              <1> 	; ...............................................................
  3395                              <1> 	;				
  3396                              <1> 	; Retro UNIX 8086 v1 modification: 
  3397                              <1> 	;       'syswrite' system call has three arguments; so,
  3398                              <1> 	;	* 1st argument, file descriptor is in BX register
  3399                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3400                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3401                              <1> 	;
  3402                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3403                              <1> 	;	to the user with number of bytes written. 
  3404                              <1> 	;
  3405 00003432 E82D000000          <1> 	call	rw1
  3406                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3407                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3408                              <1>        	; 24/12/2021
  3409 00003437 7226                <1> 	jc	short syswrite_err
  3410 00003439 F6C480              <1>         test	ah, 80h
  3411                              <1> 		; tst r1 / positive i-number ?
  3412 0000343C 7417                <1>         jz	short rw3 ; 13/05/2015
  3413                              <1> 	;jz	error
  3414                              <1> 		; bge error1 / yes, error 1 
  3415                              <1> 			   ; / negative i-number means write
  3416 0000343E 66F7D8              <1>         neg	ax
  3417                              <1> 		; neg r1 / make it positive
  3418 00003441 E867170000          <1> 	call	writei
  3419                              <1>         	; jsr r0,writei / write data
  3420                              <1> rw0: ; 1:
  3421 00003446 A1[14650000]        <1>         mov	eax, [u.nread]
  3422 0000344B A3[EC640000]        <1> 	mov	[u.r0], eax
  3423                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3424                              <1> 				  ; / into (u.r0)
  3425 00003450 E996FCFFFF          <1> 	jmp	sysret
  3426                              <1>         	; br sysret1
  3427                              <1> 
  3428                              <1> rw3: 
  3429                              <1> 	; 13/05/2015
  3430 00003455 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3430 0000345D 0000                <1>
  3431                              <1> 	;stc
  3432                              <1> 	;retn
  3433                              <1> 	; 24/12/2021 (BugFix)
  3434                              <1> sysread_err:
  3435                              <1> syswrite_err:
  3436 0000345F E967FCFFFF          <1> 	jmp	error
  3437                              <1> 
  3438                              <1> rw1:	
  3439                              <1> 	; 14/05/2015
  3440                              <1> 	; 13/05/2015
  3441                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3442                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3443                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3444                              <1> 	;
  3445                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3446                              <1> 				;(in the user's virtual memory space)
  3447                              <1> 	;mov	[u.count], edx 
  3448                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3449                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3450                              <1> 	;;mov	eax, ebx ; file descriptor
  3451                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3452                              <1> 		             ; / (index to u.fp table) in r1
  3453                              <1> 	; 13/05/2015
  3454 00003464 C705[EC640000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3454 0000346C 0000                <1>
  3455                              <1> 	;
  3456                              <1> 	;; call	getf
  3457                              <1>         ; eBX = File descriptor
  3458 0000346E E8330B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3459                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3460                              <1> 	; AX = I-number of the file ; negative i-number means write
  3461                              <1> 	; 13/05/2015
  3462 00003473 6683F801            <1> 	cmp 	ax, 1
  3463 00003477 7217                <1> 	jb	short rw2
  3464                              <1> 	;
  3465 00003479 890D[0C650000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3466                              <1> 				;(in the user's virtual memory space)
  3467 0000347F 8915[10650000]      <1> 	mov	[u.count], edx 
  3468                              <1> 	; 14/05/2015
  3469 00003485 C705[41650000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3469 0000348D 0000                <1>
  3470 0000348F C3                  <1> 	retn
  3471                              <1>         	; rts r0
  3472                              <1> rw2:
  3473                              <1> 	; 13/05/2015
  3474 00003490 C705[41650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3474 00003498 0000                <1>
  3475 0000349A C3                  <1> 	retn
  3476                              <1> 
  3477                              <1> sysopen: ;<open file>
  3478                              <1> 	; 09/01/2022
  3479                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3480                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3481                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3482                              <1> 	;
  3483                              <1> 	; 'sysopen' opens a file in following manner:
  3484                              <1> 	;    1) The second argument in a sysopen says whether to
  3485                              <1> 	;	open the file ro read (0) or write (>0).
  3486                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3487                              <1> 	;    3) The file is opened by 'iopen'.
  3488                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3489                              <1> 	;	and the user's open file list - u.fp.
  3490                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3491                              <1> 	;	b) An entry for the file is created in the fsp table.
  3492                              <1> 	;	c) The number of this entry is put on u.fp list.
  3493                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3494                              <1> 	;	   to by u.r0.
  3495                              <1> 	;
  3496                              <1> 	; Calling sequence:
  3497                              <1> 	;	sysopen; name; mode
  3498                              <1> 	; Arguments:
  3499                              <1> 	;	name - file name or path name
  3500                              <1> 	;	mode - 0 to open for reading
  3501                              <1> 	;	       1 to open for writing
  3502                              <1> 	; Inputs: (arguments)
  3503                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3504                              <1> 	;		  is put into r0's location on the stack.	
  3505                              <1> 	; ...............................................................
  3506                              <1> 	;				
  3507                              <1> 	; Retro UNIX 8086 v1 modification: 
  3508                              <1> 	;       'sysopen' system call has two arguments; so,
  3509                              <1> 	;	* 1st argument, name is pointed to by BX register
  3510                              <1> 	;	* 2nd argument, mode is in CX register
  3511                              <1> 	;
  3512                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3513                              <1> 	;	to the user with the file descriptor/number 
  3514                              <1> 	;	(index to u.fp list).
  3515                              <1> 	;
  3516                              <1> 	;call	arg2
  3517                              <1> 	; * name - 'u.namep' points to address of file/path name
  3518                              <1> 	;          in the user's program segment ('u.segmnt')
  3519                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3520                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3521                              <1> 	;          which is on top of stack.
  3522                              <1> 	;
  3523                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3524                              <1> 	;
  3525                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3526                              <1> 
  3527 0000349B 891D[04650000]      <1> 	mov	[u.namep], ebx
  3528                              <1> 	; 24/12/2021 (cx -> ecx)
  3529 000034A1 51                  <1> 	push	ecx ; * 
  3530 000034A2 E8300B0000          <1> 	call	namei
  3531                              <1> 		; jsr r0,namei / i-number of file in r1
  3532                              <1>      	;and	ax, ax
  3533                              <1> 	;jz	error ; File not found
  3534 000034A7 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3535                              <1> 	;jc	error ; 27/05/2013
  3536                              <1> 		; br  error2 / file not found
  3537                              <1>    	; 24/12/2021
  3538                              <1> 	;pop	edx ; * ; mode
  3539                              <1> 	;push	edx ; *
  3540 000034A9 8B1424              <1> 	mov	edx, [esp] ; *
  3541                              <1> 	; edx = open mode (0 or 1)
  3542                              <1> 	;or	dx, dx
  3543 000034AC 08D2                <1> 	or	dl, dl
  3544                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3545                              <1> 		         ; / 0 means, open for read)
  3546 000034AE 7403                <1> 	jz	short sysopen_0
  3547                              <1> 		; beq 1f / yes, leave i-number positive
  3548                              <1> syscreat_0: ; 27/12/2015
  3549 000034B0 66F7D8              <1> 	neg	ax
  3550                              <1>         	; neg r1 / open for writing so make i-number negative
  3551                              <1> sysopen_0: ;1:
  3552 000034B3 E8931B0000          <1> 	call	iopen
  3553                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3554 000034B8 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3555                              <1> 	;and	dx, dx
  3556 000034B9 20D2                <1> 	and	dl, dl
  3557                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3558 000034BB 7403                <1> 	jz	short sysopen_2
  3559                              <1>         	; beq op1 / is open for read op1
  3560                              <1> sysopen_1: ;op0:
  3561 000034BD 66F7D8              <1> 	neg	ax
  3562                              <1>         	; neg r1 
  3563                              <1> 	;; NOTE: iopen always make i-number positive.
  3564                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3565                              <1> sysopen_2: ;op1:
  3566 000034C0 31F6                <1>         xor     esi, esi
  3567                              <1>         	; clr r2 / clear registers
  3568 000034C2 31DB                <1>         xor     ebx, ebx
  3569                              <1> 		; clr r3
  3570                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3571 000034C4 389E[F2640000]      <1>         cmp     [esi+u.fp], bl ; 0
  3572                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3573 000034CA 7625                <1>         jna      short sysopen_4
  3574                              <1> 		; beq 1f / if byte in list is 0 branch
  3575 000034CC 46                  <1>         inc     esi
  3576                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3577 000034CD 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3578                              <1> 		; cmp r2,$10. / reached end of list?
  3579 000034D1 72F1                <1> 	jb	short sysopen_3
  3580                              <1> 		; blt 1b / no, go back
  3581                              <1> toomanyf:
  3582                              <1> 	; 14/05/2015
  3583 000034D3 C705[41650000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3583 000034DB 0000                <1>
  3584 000034DD E9E9FBFFFF          <1> 	jmp	error
  3585                              <1>         	; br error2 / yes, error (no files open)
  3586                              <1> fnotfound: 
  3587                              <1> 	; 14/05/2015
  3588 000034E2 C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3588 000034EA 0000                <1>
  3589 000034EC E9DAFBFFFF          <1> 	jmp	error
  3590                              <1> 
  3591                              <1> sysopen_4: ; 1:
  3592 000034F1 6683BB[B4620000]00  <1>         cmp     word [ebx+fsp], 0
  3593                              <1> 		; tst fsp(r3) / scan fsp entries
  3594 000034F9 760D                <1>         jna     short sysopen_5
  3595                              <1> 		; beq 1f / if 0 branch
  3596                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3597 000034FB 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3598                              <1> 		; add $8.,r3 / add 8 to r3 
  3599                              <1> 			; / to bump it to next entry mfsp table
  3600 000034FF 6681FBF401          <1>         cmp     bx, nfiles*10
  3601                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3602 00003504 72EB                <1> 	jb	short sysopen_4
  3603                              <1>        		; blt 1b / no, back
  3604                              <1> 	;jmp	error
  3605                              <1>         ;	; br error2 / yes, error
  3606                              <1> 	; 24/12/2021
  3607 00003506 EBCB                <1> 	jmp	short toomanyf
  3608                              <1> 
  3609                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3610 00003508 668983[B4620000]    <1>         mov     [ebx+fsp], ax
  3611                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3612                              <1> 			; / into next available entry in fsp table,
  3613                              <1> 	; 09/01/2022
  3614                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3615                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3616                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3617                              <1> 	;xor	edi, edi
  3618                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3619                              <1> 	;	; clr fsp+4(r3)
  3620                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3621                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3622 0000350F 31C0                <1> 	xor	eax, eax
  3623 00003511 8983[B8620000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3624 00003517 668983[BC620000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3625                              <1> 
  3626 0000351E A0[D3640000]        <1> 	mov	al, [cdev]
  3627 00003523 668983[B6620000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3628                              <1> 
  3629 0000352A 89D8                <1>   	mov	eax, ebx
  3630 0000352C B30A                <1> 	mov	bl, 10
  3631 0000352E F6F3                <1> 	div	bl 
  3632                              <1> 		; asr r3
  3633                              <1> 		; asr r3 / divide by 8 
  3634                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3635 00003530 FEC0                <1> 	inc	al
  3636                              <1>         	; inc r3 / add 1 to get fsp entry number
  3637 00003532 8886[F2640000]      <1>         mov     [esi+u.fp], al
  3638                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3639                              <1> 			; / next available slot in u.fp list
  3640 00003538 8935[EC640000]      <1>         mov     [u.r0], esi
  3641                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3642                              <1> 			     ; / into r0 loc on stack
  3643 0000353E E9A8FBFFFF          <1>         jmp	sysret
  3644                              <1> 		; br sysret2
  3645                              <1> 
  3646                              <1> 	;
  3647                              <1> 	; 'fsp' table (10 bytes/entry)
  3648                              <1> 	; bit 15				   bit 0
  3649                              <1> 	; ---|-------------------------------------------
  3650                              <1> 	; r/w|		i-number of open file
  3651                              <1> 	; ---|-------------------------------------------
  3652                              <1> 	;		   device number
  3653                              <1> 	; -----------------------------------------------
  3654                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3655                              <1> 	; -----------------------------------------------
  3656                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3657                              <1> 	; ----------------------|------------------------
  3658                              <1> 	;  flag that says file 	| number of processes
  3659                              <1> 	;   has been deleted	| that have file open 
  3660                              <1> 	; ----------------------|------------------------
  3661                              <1> 	;
  3662                              <1> 
  3663                              <1> syscreat: ; < create file >
  3664                              <1> 	; 24/12/2021
  3665                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3666                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3667                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3668                              <1> 	;
  3669                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3670                              <1> 	; u.namep points to name of the file and mode is put
  3671                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3672                              <1> 	; If the file aready exists, it's mode and owner remain 
  3673                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3674                              <1> 	; did not exist, an i-node is created with the new mode via
  3675                              <1> 	; 'maknod' whether or not the file already existed, it is
  3676                              <1> 	; open for writing. The fsp table is then searched for a free
  3677                              <1> 	; entry. When a free entry is found, proper data is placed
  3678                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3679                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3680                              <1> 	; is put in the user's r0. 			
  3681                              <1> 	;
  3682                              <1> 	; Calling sequence:
  3683                              <1> 	;	syscreate; name; mode
  3684                              <1> 	; Arguments:
  3685                              <1> 	;	name - name of the file to be created
  3686                              <1> 	;	mode - mode of the file to be created
  3687                              <1> 	; Inputs: (arguments)
  3688                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3689                              <1> 	;		   (the file descriptor of new file)
  3690                              <1> 	; ...............................................................
  3691                              <1> 	;				
  3692                              <1> 	; Retro UNIX 8086 v1 modification: 
  3693                              <1> 	;       'syscreate' system call has two arguments; so,
  3694                              <1> 	;	* 1st argument, name is pointed to by BX register
  3695                              <1> 	;	* 2nd argument, mode is in CX register
  3696                              <1> 	;
  3697                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3698                              <1> 	;	to the user with the file descriptor/number 
  3699                              <1> 	;	(index to u.fp list).
  3700                              <1> 	;
  3701                              <1> 	;call	arg2
  3702                              <1> 	; * name - 'u.namep' points to address of file/path name
  3703                              <1> 	;          in the user's program segment ('u.segmnt')
  3704                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3705                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3706                              <1> 	;          which is on top of stack.
  3707                              <1> 	;
  3708                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3709                              <1> 			    ; / on stack
  3710 00003543 891D[04650000]      <1> 	mov	[u.namep], ebx ; file name address
  3711                              <1> 	;push	cx ; mode
  3712                              <1> 	; 24/12/2021
  3713 00003549 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3714 0000354A E8880A0000          <1> 	call 	namei        	
  3715                              <1> 		; jsr r0,namei / get the i-number
  3716                              <1>         ;and	ax, ax
  3717                              <1> 	;jz	short syscreat_2	       	
  3718 0000354F 721B                <1> 	jc	short syscreat_2
  3719                              <1> 		; br  2f / if file doesn't exist 2f
  3720                              <1> 	; 27/12/2015
  3721 00003551 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3722                              <1>         ;jb	syscreat_0 ; yes
  3723                              <1> 	; 24/12/2021
  3724 00003555 7305                <1> 	jnb	short syscreat_1
  3725 00003557 E954FFFFFF          <1> 	jmp	syscreat_0
  3726                              <1> syscreat_1:
  3727 0000355C 66F7D8              <1> 	neg 	ax
  3728                              <1>         	; neg r1 / if file already exists make i-number 
  3729                              <1> 		       ; / negative (open for writing)
  3730 0000355F E8E71A0000          <1> 	call	iopen
  3731                              <1>         	; jsr r0,iopen /
  3732 00003564 E8AA130000          <1> 	call	itrunc
  3733                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3734                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3735                              <1> 	; 04/12/2021
  3736 00003569 59                  <1> 	pop	ecx
  3737                              <1> 	; 08/01/2022
  3738 0000356A EB0E                <1> 	jmp	short syscreat_3
  3739                              <1>         ;jmp	sysopen_1
  3740                              <1>         	; br op0
  3741                              <1> syscreat_2: ; 2: / file doesn't exist
  3742                              <1> 	;pop	ax
  3743                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3744                              <1> 	; 24/12/2021
  3745 0000356C 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3746 0000356D 30E4                <1> 	xor	ah, ah	
  3747                              <1>         	; bic $!377,r1 / clear upper byte
  3748 0000356F E86F0D0000          <1> 	call 	maknod
  3749                              <1>         	; jsr r0,maknod / make an i-node for this file
  3750 00003574 66A1[1E650000]      <1> 	mov	ax, [u.dirbuf]
  3751                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3752                              <1> 			        ; / for this new file in r1
  3753                              <1> syscreat_3:
  3754 0000357A E93EFFFFFF          <1>         jmp     sysopen_1
  3755                              <1>         	; br op0 / open the file
  3756                              <1> 
  3757                              <1> sysmkdir: ; < make directory >
  3758                              <1> 	; 26/02/2022
  3759                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3760                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3761                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3762                              <1> 	;
  3763                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3764                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3765                              <1> 	; The special entries '.' and '..' are not present.
  3766                              <1> 	; Errors are indicated if the directory already exists or		
  3767                              <1> 	; user is not the super user. 
  3768                              <1> 	;
  3769                              <1> 	; Calling sequence:
  3770                              <1> 	;	sysmkdir; name; mode
  3771                              <1> 	; Arguments:
  3772                              <1> 	;	name - points to the name of the directory
  3773                              <1> 	;	mode - mode of the directory
  3774                              <1> 	; Inputs: (arguments)
  3775                              <1> 	; Outputs: -
  3776                              <1> 	;    (sets 'directory' flag to 1; 
  3777                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3778                              <1> 	; ...............................................................
  3779                              <1> 	;				
  3780                              <1> 	; Retro UNIX 8086 v1 modification: 
  3781                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3782                              <1> 	;	* 1st argument, name is pointed to by BX register
  3783                              <1> 	;	* 2nd argument, mode is in CX register
  3784                              <1> 	;
  3785                              <1> 		
  3786                              <1> ; / make a directory
  3787                              <1> 
  3788                              <1> 	;call	arg2
  3789                              <1> 	; * name - 'u.namep' points to address of file/path name
  3790                              <1> 	;          in the user's program segment ('u.segmnt')
  3791                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3792                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3793                              <1> 	;          which is on top of stack.
  3794                              <1> 
  3795                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3796                              <1> 			    ; / on stack
  3797 0000357F 891D[04650000]      <1> 	mov	[u.namep], ebx
  3798                              <1> 	;push	cx ; mode
  3799                              <1> 	; 24/12/2021
  3800 00003585 51                  <1> 	push	ecx ; cx = mode
  3801 00003586 E84C0A0000          <1> 	call	namei
  3802                              <1>         	; jsr r0,namei / get the i-number
  3803                              <1>         	;     br .+4 / if file not found branch around error
  3804                              <1>         ;xor 	ax, ax
  3805                              <1> 	;jnz	error
  3806 0000358B 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3807                              <1> 	;jnc	error	
  3808                              <1> 		; br  error2 / directory already exists (error)
  3809 0000358D 803D[38650000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3810                              <1>         	;tstb u.uid / is user the super user
  3811                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3812                              <1> 	;;jna	error
  3813                              <1> 	; 26/02/2022 (BugFix)
  3814 00003594 7721                <1> 	ja	short dir_access_err
  3815                              <1>         	;bne error2 / no, not allowed
  3816                              <1> 	;pop	ax
  3817                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3818                              <1> 	; 24/12/2021
  3819 00003596 58                  <1> 	pop	eax  ; ax = mode
  3820 00003597 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3821                              <1>         	;bic $!317,r1 / all but su and ex
  3822                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3823 0000359B 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3824                              <1>         	;bis $40000,r1 / directory flag
  3825 0000359E E8400D0000          <1> 	call	maknod
  3826                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3827                              <1> ;sysclose_sysret: ; 26/02/2022
  3828 000035A3 E943FBFFFF          <1> 	jmp	sysret
  3829                              <1>         	;br sysret2 /
  3830                              <1> dir_exists:
  3831                              <1> 	; 14/05/2015
  3832 000035A8 C705[41650000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3832 000035B0 0000                <1>
  3833 000035B2 E914FBFFFF          <1> 	jmp	error
  3834                              <1> dir_access_err:
  3835                              <1> 	; 14/05/2015
  3836 000035B7 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3836 000035BF 0000                <1>
  3837 000035C1 E905FBFFFF          <1> 	jmp	error
  3838                              <1> 
  3839                              <1> sysclose: ;<close file>
  3840                              <1> 	; 26/02/2022
  3841                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3842                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3843                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3844                              <1> 	;
  3845                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3846                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3847                              <1> 	; is put in r1 and 'fclose' is called.
  3848                              <1> 	;
  3849                              <1> 	; Calling sequence:
  3850                              <1> 	;	sysclose
  3851                              <1> 	; Arguments:
  3852                              <1> 	;	-  
  3853                              <1> 	; Inputs: *u.r0 - file descriptor
  3854                              <1> 	; Outputs: -
  3855                              <1> 	; ...............................................................
  3856                              <1> 	;				
  3857                              <1> 	; Retro UNIX 8086 v1 modification:
  3858                              <1> 	;	 The user/application program puts file descriptor
  3859                              <1> 	;        in BX register as 'sysclose' system call argument.
  3860                              <1> 	; 	 (argument transfer method 1)
  3861                              <1> 
  3862                              <1> 	; / close the file
  3863                              <1> 	
  3864 000035C6 89D8                <1> 	mov 	eax, ebx
  3865 000035C8 E896090000          <1> 	call 	fclose
  3866                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3867                              <1> 		; jsr r0,fclose / close the file
  3868                              <1>                	; br error2 / unknown file descriptor
  3869                              <1> 		; br sysret2
  3870                              <1> 	; 14/05/2015
  3871                              <1> 	;jnc	sysret
  3872                              <1> 	; 04/12/2021
  3873 000035CD 7205                <1> 	jc	short sysclose_err
  3874 000035CF E917FBFFFF          <1> 	jmp	sysret
  3875                              <1> 	; 26/02/2022
  3876                              <1> 	;jnc	short sysclose_sysret
  3877                              <1> sysclose_err:
  3878 000035D4 C705[41650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3878 000035DC 0000                <1>
  3879 000035DE E9E8FAFFFF          <1> 	jmp	error
  3880                              <1> 
  3881                              <1> sysemt:
  3882                              <1> 	; 26/02/2022
  3883                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3884                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3885                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3886                              <1> 	;
  3887                              <1> 	; Retro UNIX 8086 v1 modification: 
  3888                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3889                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3890                              <1> 	;
  3891                              <1> 	; Retro UNIX 8086 v1 feature only!
  3892                              <1> 	;	Using purpose: Kernel will start without time-out
  3893                              <1> 	;	(internal clock/timer) functionality.
  3894                              <1> 	;	Then etc/init will enable clock/timer for
  3895                              <1> 	;	multi tasking. (Then it will not be disabled again
  3896                              <1> 	;	except hardware reset/restart.)
  3897                              <1> 	;
  3898                              <1> 
  3899 000035E3 803D[38650000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3900                              <1> 	;;ja	error
  3901                              <1> 	;ja	badsys ; 14/05/2015
  3902                              <1> 	; 24/12/2021
  3903 000035EA 7605                <1> 	jna	short emt_0 
  3904 000035EC E98CFBFFFF          <1> 	jmp	badsys
  3905                              <1> emt_0:
  3906                              <1> 	; 24/12/2021
  3907                              <1> 	;cli
  3908 000035F1 21DB                <1> 	and	ebx, ebx
  3909 000035F3 7429                <1> 	jz	short emt_2
  3910                              <1> 	; Enable multi tasking -time sharing-
  3911 000035F5 B8[9C450000]        <1> 	mov	eax, clock
  3912                              <1> 	; 26/02/2022
  3913 000035FA BA[2C0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3914                              <1> emt_1:
  3915 000035FF A3[F1060000]        <1> 	mov	[x_timer], eax
  3916                              <1> 	; 26/02/2022 (Temporary)
  3917 00003604 8915[F5060000]      <1> 	mov	[x_rtci], edx
  3918 0000360A B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3919 0000360C E851020000          <1> 	call	wttyc  ; clear video page
  3920 00003611 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3921 00003613 E84A020000          <1> 	call	wttyc  ; clear video page
  3922                              <1> 	;
  3923 00003618 FB                  <1> 	sti
  3924 00003619 E9CDFAFFFF          <1> 	jmp	sysret
  3925                              <1> emt_2:
  3926                              <1> 	; Disable multi tasking -time sharing-
  3927 0000361E B8[FD060000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3928                              <1> 	; 26/02/2022
  3929 00003623 BA[330A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3930                              <1> 	;
  3931 00003628 EBD5                <1> 	jmp	short emt_1
  3932                              <1> 
  3933                              <1> 	; Original UNIX v1 'sysemt' routine
  3934                              <1> ;sysemt:
  3935                              <1>         ;
  3936                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3937                              <1> 			 ; / in loc 30
  3938                              <1>         ;cmp    30,$core / was the argument a lower address 
  3939                              <1> 			; / than core
  3940                              <1>         ;blo    1f / yes, rtssym
  3941                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3942                              <1> 			; / and less than "ecore"
  3943                              <1>         ;blo    2f / yes, sysret2
  3944                              <1> ;1:
  3945                              <1>         ;mov    $rtssym,30
  3946                              <1> ;2:
  3947                              <1>         ;br     sysret2
  3948                              <1> 
  3949                              <1> sysilgins:
  3950                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3951                              <1> 	; 03/06/2013
  3952                              <1> 	; Retro UNIX 8086 v1 modification: 
  3953                              <1> 	;	not a valid system call ! (not in use)
  3954                              <1> 	;
  3955 0000362A E94EFBFFFF          <1> 	jmp	badsys
  3956                              <1> 	;jmp	error
  3957                              <1> 	;;jmp 	sysret
  3958                              <1> 
  3959                              <1> 	; Original UNIX v1 'sysemt' routine
  3960                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3961                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3962                              <1> 			  ;/ put it in loc 8.,
  3963                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3964                              <1> 		       ; / trap address
  3965                              <1>         ;blo    1f / is the address a user core address?  
  3966                              <1> 		; / yes, go to 2f
  3967                              <1>         ;cmp    10,$ecore
  3968                              <1>         ;blo    2f
  3969                              <1> ;1:
  3970                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3971                              <1> 		    ; / instruction trap address for the system
  3972                              <1> ;2:
  3973                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3974                              <1> 
  3975                              <1> sysmdate: ; < change the modification time of a file >
  3976                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3977                              <1> 	;	(ECX input)
  3978                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3979                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3980                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3981                              <1> 	;
  3982                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3983                              <1> 	; file into core. The user is checked if he is the owner 
  3984                              <1> 	; or super user. If he is neither an error occurs.
  3985                              <1> 	; 'setimod' is then called to set the i-node modification
  3986                              <1> 	; byte and the modification time, but the modification time
  3987                              <1> 	; is overwritten by whatever get put on the stack during
  3988                              <1> 	; a 'systime' system call. This calls are restricted to
  3989                              <1> 	; the super user.		
  3990                              <1> 	;
  3991                              <1> 	; Calling sequence:
  3992                              <1> 	;	sysmdate; name
  3993                              <1> 	; Arguments:
  3994                              <1> 	;	name - points to the name of file
  3995                              <1> 	; Inputs: (arguments)
  3996                              <1> 	; Outputs: -
  3997                              <1> 	; ...............................................................
  3998                              <1> 	;				
  3999                              <1> 	; Retro UNIX 8086 v1 modification: 
  4000                              <1> 	;	 The user/application program puts address 
  4001                              <1> 	;	 of the file name in BX register 
  4002                              <1> 	;	 as 'sysmdate' system call argument.
  4003                              <1> 	;
  4004                              <1> ; / change the modification time of a file
  4005                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4006 0000362F 891D[04650000]      <1>         mov	[u.namep], ebx
  4007                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  4008 00003635 890D[70610000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  4009 0000363B E897090000          <1> 	call	namei
  4010                              <1> 		; jsr r0,namei / get its i-number
  4011                              <1> 	;;jc	error       
  4012                              <1> 	;	; br error2 / no, such file
  4013                              <1> 	;jc	fnotfound ; file not found !
  4014                              <1> 	; 24/12/2021
  4015 00003640 7305                <1> 	jnc	short mdate_0
  4016 00003642 E99BFEFFFF          <1> 	jmp	fnotfound
  4017                              <1> mdate_0:
  4018 00003647 E89B110000          <1> 	call	iget
  4019                              <1> 		; jsr r0,iget / get i-node into core
  4020 0000364C A0[38650000]        <1> 	mov	al, [u.uid]
  4021 00003651 3A05[E7610000]      <1> 	cmp	al, [i.uid]
  4022                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  4023 00003657 7413                <1> 	je	short mdate_1
  4024                              <1>         	; beq 1f / yes
  4025 00003659 20C0                <1> 	and	al, al
  4026                              <1> 		; tstb u.uid / no, is user the super user
  4027                              <1> 	;jnz	error
  4028                              <1> 		; bne error2 / no, error
  4029 0000365B 740F                <1> 	jz	short mdate_1
  4030 0000365D C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4030 00003665 0000                <1>
  4031                              <1> sysstty_err:	; 04/02/2022
  4032 00003667 E95FFAFFFF          <1> 	jmp	error
  4033                              <1> mdate_1: ;1:
  4034 0000366C E880120000          <1> 	call	setimod
  4035                              <1>         	; jsr r0,setimod / fill in modification data,
  4036                              <1> 		               ; / time etc.
  4037 00003671 BE[70610000]        <1> 	mov	esi, p_time
  4038 00003676 BF[FE610000]        <1> 	mov	edi, i.mtim
  4039 0000367B A5                  <1> 	movsd
  4040                              <1> 		; mov 4(sp),i.mtim / move present time to
  4041                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4042 0000367C E96AFAFFFF          <1>         jmp	sysret
  4043                              <1> 		; br sysret2
  4044                              <1> 
  4045                              <1> 	; 04/02/2022
  4046                              <1> sysstty_err_s:
  4047 00003681 880D[EC640000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4048 00003687 EBDE                <1> 	jmp	short sysstty_err
  4049                              <1> 
  4050                              <1> sysstty: ; < set tty status and mode >
  4051                              <1> 	; 26/02/2022
  4052                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4053                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4054                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4055                              <1> 	; 17/11/2015
  4056                              <1> 	; 12/11/2015
  4057                              <1> 	; 29/10/2015
  4058                              <1> 	; 17/10/2015
  4059                              <1> 	; 13/10/2015
  4060                              <1> 	; 29/06/2015
  4061                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4062                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4063                              <1> 	;
  4064                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4065                              <1> 	; whose file descriptor is in (u.r0).
  4066                              <1> 	;
  4067                              <1> 	; Calling sequence:
  4068                              <1> 	;	sysstty; arg
  4069                              <1> 	; Arguments:
  4070                              <1> 	;	arg - address of 3 consequitive words that contain
  4071                              <1> 	;	      the source of status data	
  4072                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4073                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4074                              <1> 	; ...............................................................
  4075                              <1> 	;	
  4076                              <1> 	; Retro UNIX 8086 v1 modification: 
  4077                              <1> 	;	'sysstty' system call will set the tty
  4078                              <1> 	;	(clear keyboard buffer and set cursor position)
  4079                              <1> 	;	 in following manner:
  4080                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4081                              <1> 	;
  4082                              <1> 	; Inputs:
  4083                              <1> 	;	BX = 0 --> means
  4084                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4085                              <1> 	;	      set cursor position for console tty, only 
  4086                              <1> 	;	      CH will be ignored (char. will not be written)	
  4087                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4088                              <1> 	;	      set console tty for (current) process
  4089                              <1> 	;	      CL = tty number (0 to 9)
  4090                              <1> 	;	      (If CH = 0, character will not be written)			
  4091                              <1> 	;          If CH > 0 (CL < FFh)	
  4092                              <1> 	;             CL = tty number (0 to 9)
  4093                              <1> 	;	      CH = character will be written
  4094                              <1> 	;	        at requested cursor position (in DX)	
  4095                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4096                              <1>   	;		(only tty number 0 to 7) 
  4097                              <1> 	;          DL = communication parameters (for serial ports) 
  4098                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4099                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4100                              <1> 	;			or set cursor position	
  4101                              <1> 	;	   DH = 0FFh -> DL is not valid
  4102                              <1> 	;		do not set serial port parameters 
  4103                              <1> 	;		or do not set cursor position
  4104                              <1> 	;
  4105                              <1> 	;	BX > 0 --> points to name of tty
  4106                              <1> 	;    	   CH > 0 -->
  4107                              <1> 	;		CH = character will be written in current 
  4108                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4109                              <1> 	;	     	or character will be sent to serial port
  4110                              <1> 	;	     	(for tty number 8 or 9)
  4111                              <1> 	;		CL = color of the character if tty number < 8.
  4112                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4113                              <1> 	;		set mode (tty 8 to 9) or 
  4114                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4115                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4116                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4117                              <1> 	;		(DL is not valid)
  4118                              <1> 	;	   DL = communication parameters 
  4119                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4120                              <1> 	;
  4121                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4122                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4123                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4124                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4125                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4126                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4127                              <1> 	;
  4128                              <1> 	; Outputs:
  4129                              <1> 	;	cf = 0 -> OK
  4130                              <1> 	;	     AL = tty number (0 to 9)
  4131                              <1> 	;	     AH = line status if tty number is 8 or 9
  4132                              <1> 	;	     AH = process number (of the caller) 	
  4133                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4134                              <1> 	;	     AH = FFh if the tty is locked 
  4135                              <1> 	;		  (owned by another process)
  4136                              <1> 	;	        = process number (of the caller) 
  4137                              <1> 	;		  (if < FFh and tty number < 8)
  4138                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4139                              <1> 	;	     AH = line status if tty number is 8 or 9
  4140                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4141                              <1> 	;	
  4142                              <1> 
  4143                              <1> 	; 27/06/2015 (32 bit modifications)
  4144                              <1> 	; 14/01/2014
  4145 00003689 31C0                <1> 	xor 	eax, eax
  4146 0000368B 6648                <1> 	dec	ax ; 17/10/2015
  4147 0000368D A3[EC640000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4148                              <1> 	;;;
  4149                              <1> 	; 01/02/2022
  4150 00003692 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4151 00003694 39C2                <1> 	cmp	edx, eax
  4152                              <1> 	;cmp	dx, ax ; 0FFFFh
  4153 00003696 7521                <1> 	jne	short sysstty_18
  4154                              <1> 	; clear video page
  4155                              <1> 	; (CH must be 0)
  4156 00003698 08ED                <1> 	or	ch, ch
  4157 0000369A 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4158 0000369C 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4159 0000369F 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4160 000036A1 20C9                <1> 	and	cl, cl
  4161 000036A3 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4162 000036A5 0FB635[3B650000]    <1> 	movzx	esi, byte [u.uno]
  4163 000036AC 8A8E[43620000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4164 000036B2 80F907              <1> 	cmp	cl, 7
  4165 000036B5 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4166                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4167 000036B7 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4168                              <1> sysstty_18:
  4169 000036B9 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4170                              <1> 	; cl = video page (tty) number		
  4171                              <1> 	;;;
  4172 000036BB 21DB                <1> 	and	ebx, ebx
  4173                              <1> 	;jnz	sysstty_6
  4174                              <1> 	; 01/02/2022
  4175 000036BD 7405                <1> 	jz	short sysstty_19
  4176 000036BF E9C2000000          <1> 	jmp	sysstty_6
  4177                              <1> sysstty_19:
  4178                              <1> 	; set console tty
  4179                              <1> 	; 29/10/2015
  4180                              <1> 	; 17/01/2014 
  4181 000036C4 80F909              <1> 	cmp	cl, 9
  4182 000036C7 7613                <1> 	jna	short sysstty_0
  4183                              <1> 	; 17/11/2015
  4184 000036C9 80F9FF              <1> 	cmp	cl, 0FFh
  4185 000036CC 7202                <1> 	jb	short sysstty_13
  4186 000036CE 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4187                              <1> sysstty_13:
  4188 000036D0 8A1D[3B650000]      <1> 	mov	bl, [u.uno] ; process number
  4189 000036D6 8A8B[43620000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4190                              <1> sysstty_0:
  4191                              <1> 	; 29/06/2015
  4192                              <1> 	;push	dx
  4193                              <1> 	;push	cx
  4194                              <1> 	; 01/02/2022
  4195 000036DC 52                  <1> 	push	edx
  4196 000036DD 51                  <1> 	push	ecx
  4197 000036DE 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4198 000036E0 88C8                <1> 	mov	al, cl
  4199 000036E2 A2[EC640000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4200 000036E7 E8F9190000          <1> 	call	ottyp
  4201                              <1> 	; 01/02/2022
  4202 000036EC 59                  <1> 	pop	ecx
  4203 000036ED 5A                  <1> 	pop	edx
  4204                              <1> 	;pop	cx
  4205                              <1> 	;pop	dx
  4206                              <1> 	;
  4207 000036EE 7220                <1> 	jc	short sysstty_pd_err
  4208                              <1> 	;
  4209                              <1> 	; 26/02/2022 (Bug! BugFix)
  4210                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4211                              <1> 	;
  4212 000036F0 80F908              <1> 	cmp	cl, 8
  4213 000036F3 720C                <1> 	jb	short sysstty_2
  4214                              <1> 	;
  4215 000036F5 80FEFF              <1> 	cmp	dh, 0FFh
  4216 000036F8 7407                <1> 	je	short sysstty_2
  4217                              <1> 		; set communication parameters for serial ports
  4218                              <1> 
  4219                              <1> ; 01/02/2022
  4220                              <1> ;	; 29/10/2015
  4221                              <1> ;	mov	ah, dl ; communication parameters
  4222                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4223                              <1> ;		;			 THRE int + RDA int 
  4224                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4225                              <1> ;		;			 THRE int + RDA int 
  4226                              <1> ;	sub	al, al ; 0
  4227                              <1> ;	; 12/07/2014
  4228                              <1> ;	cmp	cl, 9
  4229                              <1> ;	jb	short sysstty_1
  4230                              <1> ;	inc	al
  4231                              <1> ;sysstty_1:
  4232                              <1> ;	; 01/02/2022
  4233                              <1> ;	push	ecx
  4234                              <1> ;	;push	cx
  4235                              <1> ;	; 29/06/2015	
  4236                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4237                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4238                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4239                              <1> ;	; 01/02/2022
  4240                              <1> ;	pop	ecx	
  4241                              <1> ;	;pop	cx
  4242                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4243                              <1> 
  4244                              <1> 	; 01/02/2022
  4245 000036FA E830010000          <1> 	call	sysstty_scp
  4246 000036FF 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4247                              <1> 
  4248                              <1> sysstty_2:
  4249                              <1> 	; 17/01/2014
  4250 00003701 20ED                <1> 	and	ch, ch 	; set cursor position 
  4251                              <1> 			; or comm. parameters ONLY
  4252 00003703 7527                <1> 	jnz	short sysstty_3
  4253                              <1> 	; 01/02/2022
  4254 00003705 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4255 00003709 7214                <1> 	jb	short sysstty_20
  4256                              <1> 	; clear screen (video page)
  4257 0000370B E93B010000          <1> 	jmp	sysstty_14
  4258                              <1> 
  4259                              <1> sysstty_pd_err: ; 29/06/2015
  4260                              <1> 	; 'permission denied !' error
  4261 00003710 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4261 00003718 0000                <1>
  4262 0000371A E9ACF9FFFF          <1> 	jmp	error
  4263                              <1> 
  4264                              <1> sysstty_20:
  4265 0000371F 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4266 00003726 888B[43620000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4267                              <1> sysstty_3:
  4268                              <1> 	; 16/01/2014
  4269 0000372C 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4270                              <1> 	; 17/11/2015
  4271 0000372E B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4272 00003730 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4273                              <1> 	;jna	sysstty_9
  4274                              <1> 	; 01/02/2022
  4275 00003732 7705                <1> 	ja	short sysstty_12
  4276 00003734 E9C5000000          <1> 	jmp	sysstty_9
  4277                              <1> 
  4278                              <1> sysstty_12:
  4279                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4280                              <1> 	; (Set specified serial port as console tty port)
  4281                              <1> 	; CH = character to be written
  4282                              <1> 	; 15/04/2014
  4283                              <1> 	; CH = 0 --> initialization only
  4284                              <1> 	; AL = character
  4285                              <1> 	; 26/06/2014
  4286 00003739 880D[40650000]      <1> 	mov	[u.ttyn], cl
  4287                              <1> 	; 12/07/2014
  4288 0000373F 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4289                              <1> 	; 02/02/2022
  4290 00003741 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4291 00003743 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4292 00003745 FEC8                <1> 	dec	al  ; 1 -> 0	
  4293                              <1> 	;and	al, al
  4294 00003747 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4295                              <1>  	; 04/07/2014
  4296 00003749 E8AD1E0000          <1> 	call 	sndc
  4297                              <1> 	; 12/07/2014
  4298 0000374E EB0C                <1> 	jmp	short sysstty_5
  4299                              <1> 
  4300                              <1> sysstty_4:
  4301                              <1> 	; 12/07/2014
  4302                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4303 00003750 88E0                <1> 	mov	al, ah ; 29/06/2015
  4304 00003752 2C08                <1> 	sub	al, 8
  4305                              <1> 	; 27/06/2015
  4306 00003754 E828F4FFFF          <1> 	call	sp_status ; get serial port status
  4307                              <1> 	; AL = Line status, AH = Modem status
  4308                              <1> 	; 12/11/2015
  4309 00003759 3C80                <1> 	cmp	al, 80h
  4310 0000375B F5                  <1> 	cmc
  4311                              <1> sysstty_5:
  4312 0000375C 66A3[ED640000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4313                              <1> 		; EAX bits 16-23 = modem status	
  4314 00003762 9C                  <1> 	pushf
  4315 00003763 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4316 00003765 A0[40650000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4317 0000376A E8991A0000          <1> 	call	cttyp
  4318 0000376F 9D                  <1> 	popf
  4319                              <1> 	;jnc	sysret ; time out error 
  4320                              <1> 	; 01/02/2022
  4321 00003770 7205                <1> 	jc	short sysstty_tmout_err
  4322 00003772 E974F9FFFF          <1> 	jmp	sysret
  4323                              <1> 
  4324                              <1> sysstty_tmout_err:
  4325 00003777 C705[41650000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4325 0000377F 0000                <1>
  4326 00003781 E945F9FFFF          <1> 	jmp	error
  4327                              <1> 
  4328                              <1> sysstty_6:
  4329                              <1> 	;push	dx
  4330                              <1> 	;push	cx
  4331                              <1> 	; 01/02/2022
  4332 00003786 52                  <1> 	push	edx
  4333 00003787 51                  <1> 	push	ecx
  4334 00003788 891D[04650000]      <1> 	mov	[u.namep], ebx
  4335 0000378E E844080000          <1> 	call	namei
  4336                              <1> 	; 01/02/2022
  4337 00003793 59                  <1> 	pop	ecx
  4338 00003794 5A                  <1> 	pop	edx
  4339                              <1> 	;pop	cx
  4340                              <1> 	;pop	dx
  4341 00003795 7258                <1> 	jc	short sysstty_inv_dn
  4342                              <1> 	;
  4343 00003797 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4344 0000379B 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4345                              <1> 	;
  4346 0000379D 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4347                              <1> 		       ; /dev/COM1, /dev/COM2
  4348 0000379F 7204                <1> 	jb	short sysstty_7
  4349 000037A1 2C0A                <1> 	sub	al, 10
  4350 000037A3 EB11                <1> 	jmp	short sysstty_8
  4351                              <1> 
  4352                              <1> sysstty_7:
  4353 000037A5 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4354 000037A7 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4355 000037A9 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4356 000037B0 8A83[43620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4357                              <1> sysstty_8:
  4358                              <1> 	; 26/02/2022
  4359                              <1> 	; (ebx < 256)	
  4360 000037B6 A2[EC640000]        <1> 	mov	[u.r0], al
  4361                              <1> 	; 01/02/2022
  4362                              <1> 	;push	dx
  4363                              <1> 	;push	ax
  4364                              <1> 	;push	cx
  4365 000037BB 52                  <1> 	push	edx
  4366 000037BC 50                  <1> 	push	eax
  4367 000037BD 51                  <1> 	push	ecx	
  4368 000037BE E822190000          <1> 	call	ottyp
  4369 000037C3 59                  <1> 	pop	ecx
  4370 000037C4 58                  <1> 	pop	eax
  4371 000037C5 5A                  <1> 	pop	edx
  4372                              <1> 	;pop	cx
  4373                              <1> 	;pop	ax
  4374                              <1> 	;pop	dx
  4375                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4376                              <1> 	; 01/02/2022
  4377 000037C6 7305                <1> 	jnc	short sysstty_21
  4378 000037C8 E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4379                              <1> sysstty_21:
  4380                              <1> 	; 29/10/2015
  4381 000037CD 86E9                <1> 	xchg 	ch, cl
  4382                              <1> 		; cl = character, ch = color code
  4383 000037CF 86C1                <1> 	xchg	al, cl
  4384                              <1> 		; al = character, cl = tty number
  4385 000037D1 80F907              <1> 	cmp	cl, 7
  4386                              <1> 	;ja	sysstty_12
  4387                              <1> 	; 01/02/2022
  4388 000037D4 7628                <1> 	jna	short sysstty_16
  4389                              <1> ;;
  4390 000037D6 80FEFF              <1> 	cmp	dh, 0FFh
  4391 000037D9 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4392                              <1> 
  4393                              <1> ; 01/02/2022
  4394                              <1> ;	; 29/10/2015
  4395                              <1> ;	mov	ah, dl ; communication parameters
  4396                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4397                              <1> ;		;			 THRE int + RDA int 
  4398                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4399                              <1> ;		;			 THRE int + RDA int 
  4400                              <1> ;	sub	al, al ; 0
  4401                              <1> ;	; 12/07/2014
  4402                              <1> ;	cmp	cl, 9
  4403                              <1> ;	jb	short sysstty_1
  4404                              <1> ;	inc	al
  4405                              <1> ;sysstty_1:
  4406                              <1> ;	; 01/02/2022
  4407                              <1> ;	push	ecx
  4408                              <1> ;	;push	cx
  4409                              <1> ;	; 29/06/2015	
  4410                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4411                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4412                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4413                              <1> ;	; 01/02/2022
  4414                              <1> ;	pop	ecx	
  4415                              <1> ;	;pop	cx
  4416                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4417                              <1> 
  4418                              <1> 	; 02/02/2022
  4419 000037DB 88C5                <1> 	mov	ch, al ; save char
  4420                              <1> 	; 01/02/2022
  4421 000037DD E84D000000          <1> 	call	sysstty_scp
  4422 000037E2 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4423                              <1> 	; 02/02/2022
  4424 000037E4 88E8                <1> 	mov	al, ch ; restore char
  4425                              <1> sysstty_22:
  4426                              <1> 	; 01/02/2022
  4427 000037E6 08ED                <1> 	or	ch, ch
  4428 000037E8 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4429                              <1> 	; send char to (serial port) terminal
  4430                              <1> 	; al = character
  4431                              <1> 	; cl = tty number (8 or 9)
  4432 000037EA E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4433                              <1> 
  4434                              <1> sysstty_inv_dn: 
  4435                              <1> 	; 27/06/2015
  4436                              <1> 	; Invalid device name (not a tty) ! error
  4437                              <1> 	; (Device is not a tty or device name not found)
  4438 000037EF C705[41650000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4438 000037F7 0000                <1>
  4439 000037F9 E9CDF8FFFF          <1> 	jmp	error 
  4440                              <1> 
  4441                              <1> sysstty_16:
  4442                              <1> 	; 26/02/2022
  4443                              <1> 	; 16/01/2014
  4444                              <1> 	;xor	bh, bh
  4445                              <1> 	; 02/02/2022
  4446                              <1> sysstty_9: 	; tty 0 to tty 7
  4447                              <1> 	; al = character
  4448                              <1> 	; ch = color/attribute ; 01/02/2022
  4449                              <1> 	;
  4450                              <1> 	; 26/02/2022 (BugFix)
  4451                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4452 000037FE 29DB                <1> 	sub	ebx, ebx ; *
  4453 00003800 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4454 00003803 740B                <1> 	je	short sysstty_10
  4455                              <1> 	; 02/02/2022
  4456 00003805 51                  <1> 	push	ecx
  4457 00003806 50                  <1> 	push	eax
  4458                              <1> 	;push	cx
  4459                              <1> 	;push	ax	
  4460                              <1> 	;movzx	ebx, cl
  4461 00003807 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4462 00003809 E898DBFFFF          <1> 	call	set_cpos
  4463                              <1> 	;pop	ax
  4464                              <1> 	;pop	cx
  4465                              <1> 	; 02/02/2022
  4466 0000380E 58                  <1> 	pop	eax
  4467 0000380F 59                  <1> 	pop	ecx
  4468                              <1> sysstty_10: 
  4469                              <1> 	; 29/10/2015
  4470 00003810 08C0                <1> 	or	al, al ; character
  4471 00003812 740D                <1> 	jz      short sysstty_11 ; al = 0
  4472                              <1> 	; 17/11/2015
  4473 00003814 3CFF                <1> 	cmp	al, 0FFh
  4474 00003816 7309                <1> 	jnb	short sysstty_11
  4475                              <1> 		; ch > 0 and ch < FFh
  4476                              <1> 	; write a character at current cursor position
  4477 00003818 88EC                <1> 	mov	ah, ch ; color/attribute
  4478                              <1> 	; 12/07/2014
  4479                              <1> 	;push	cx
  4480                              <1> 	; 02/02/2022
  4481 0000381A 51                  <1> 	push	ecx
  4482 0000381B E86EDCFFFF          <1> 	call	write_c_current
  4483                              <1> 	;pop	cx
  4484                              <1> 	; 02/02/2022
  4485 00003820 59                  <1> 	pop	ecx
  4486                              <1> sysstty_11:
  4487                              <1> 	; 14/01/2014
  4488 00003821 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4489                              <1> 	; 18/01/2014
  4490                              <1> 	;movzx	eax, cl ; 27/06/2015
  4491 00003823 88C8                <1> 	mov	al, cl
  4492 00003825 E8DE190000          <1> 	call	cttyp
  4493 0000382A E9BCF8FFFF          <1> 	jmp	sysret
  4494                              <1> 
  4495                              <1> sysstty_scp:
  4496                              <1> 	; 02/02/2022
  4497                              <1> 	; set communication parameters (for COM1 or COM2)
  4498                              <1> 	; 01/02/2022
  4499                              <1> 	;
  4500                              <1> 	; 29/10/2015
  4501 0000382F 88D4                <1> 	mov	ah, dl ; communication parameters
  4502                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4503                              <1> 		;			 THRE int + RDA int 
  4504                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4505                              <1> 		;			 THRE int + RDA int 
  4506 00003831 28C0                <1> 	sub	al, al ; 0
  4507                              <1> 	; 12/07/2014
  4508 00003833 80F909              <1> 	cmp	cl, 9
  4509 00003836 7202                <1> 	jb	short sysstty_1
  4510 00003838 FEC0                <1> 	inc	al
  4511                              <1> sysstty_1:
  4512                              <1> 	; 02/02/2022
  4513 0000383A 52                  <1> 	push	edx
  4514                              <1> 	; 01/02/2022
  4515 0000383B 51                  <1> 	push	ecx
  4516                              <1> 	;push	cx
  4517                              <1> 	; 29/06/2015	
  4518 0000383C E848F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4519 00003841 66890D[ED640000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4520                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4521                              <1> 	; 01/02/2022
  4522 00003848 59                  <1> 	pop	ecx	
  4523                              <1> 	;pop	cx
  4524 00003849 5A                  <1> 	pop	edx ; 02/02/2022
  4525                              <1> 	; 01/02/2022
  4526                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4527 0000384A C3                  <1> 	retn
  4528                              <1> 
  4529                              <1> sysstty_14:
  4530                              <1> 	; 26/02/2022
  4531                              <1> 	; 02/02/2022
  4532                              <1> 	; ch = 0
  4533                              <1> 	; cl = video page
  4534                              <1> 	;
  4535                              <1> 	; dx = 0FFFFh
  4536                              <1> 	; clear screen (video page)
  4537                              <1> 	;
  4538                              <1> 
  4539                              <1> 	; 02/02/2022
  4540                              <1> 	; clear screen
  4541                              <1> 	;
  4542                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4543                              <1> 	; clear video page
  4544                              <1> 
  4545                              <1> 	; 26/02/2022
  4546 0000384B 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4547                              <1> 
  4548                              <1> 	; clear video page
  4549 0000384D E810000000          <1> 	call	wttyc ; 26/02/2022
  4550                              <1> 
  4551                              <1> 	; 26/02/2022
  4552 00003852 88D8                <1> 	mov	al, bl
  4553 00003854 8A25[3B650000]      <1> 	mov	ah, [u.uno]
  4554 0000385A 66A3[EC640000]      <1> 	mov	[u.r0], ax
  4555 00003860 EBBF                <1> 	jmp	short sysstty_11
  4556                              <1> 
  4557                              <1> vp_clr:	; 27/02/2022
  4558                              <1> wttyc:
  4559                              <1> 	; 23/02/2022
  4560                              <1> 	; (clear video page)
  4561                              <1> 	; INPUT:
  4562                              <1> 	;  bl = video page (0 to 7)
  4563                              <1> 	;
  4564                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4565                              <1> 
  4566                              <1> 	;xor	dx, dx ; column 0, row 0
  4567                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4568                              <1> 	;
  4569                              <1> ;	movzx	ebx, cl
  4570                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4571                              <1> 
  4572                              <1> ;	shl 	bl, 1 
  4573                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4574                              <1> ;		; AL = lock value (0 or process number)
  4575                              <1> ;	or	al, al
  4576                              <1> ;	jz	short @f
  4577                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4578                              <1> ;	jne	short sysstty_15
  4579                              <1> ;		; only the owner can clear its video page
  4580                              <1> ;	xor	al, al ; 0
  4581                              <1> ;@@:
  4582                              <1> ;	;mov	bl, cl		
  4583                              <1> ;	shr	bl, 1 
  4584                              <1> 
  4585 00003862 30C0                <1> 	xor	al, al	; 0
  4586 00003864 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4587                              <1> 
  4588                              <1> 	; scroll_up input:
  4589                              <1> 	;
  4590                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4591                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4592                              <1> 	; ah = attribute to be used on blanked line
  4593                              <1> 	; bl = video page number (0 to 7)
  4594                              <1> 
  4595 00003866 E8C1DBFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4596                              <1> 
  4597                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4598                              <1> 
  4599                              <1> 	; bl = video page number (0 to 7)
  4600                              <1> 	;xor	dx, dx ; column 0, row 0
  4601                              <1> 	; 02/02/2022
  4602 0000386B 31D2                <1> 	xor	edx, edx
  4603                              <1> 	; 26/02/2022
  4604                              <1> 	;call	set_cpos
  4605                              <1> 	;retn
  4606 0000386D E934DBFFFF          <1> 	jmp	set_cpos
  4607                              <1> 
  4608                              <1> 	;mov	al, bl
  4609                              <1> 	;mov	ah, [u.uno]
  4610                              <1> 	;mov	[u.r0], ax
  4611                              <1> 	;jmp	short sysstty_11
  4612                              <1> 
  4613                              <1> ;sysstty_15:
  4614                              <1> ;	; 30/01/2022
  4615                              <1> ;	; permission (denied) error
  4616                              <1> ;	;xor	dl, dl ; sysstty call sign
  4617                              <1> ;	mov	al, cl
  4618                              <1> ;	sub	ah, ah ; 0
  4619                              <1> ;	call	cttyp
  4620                              <1> ;	jmp	error
  4621                              <1> 
  4622                              <1> ; Original UNIX v1 'sysstty' routine:
  4623                              <1> ; gtty:
  4624                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4625                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4626                              <1> 	; 		/ r2 has source
  4627                              <1>         ;mov    r2,-(sp)
  4628                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4629                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4630                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4631                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4632                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4633                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4634                              <1>         ;       br .+4 / list empty, skip branch
  4635                              <1>         ;br     1b / get another character until list is empty
  4636                              <1>         ;mov    0b,r1 / move cc offset to r1
  4637                              <1>         ;inc    r1 / bump it for output clist
  4638                              <1>         ;tstb   cc(r1) / is it 0
  4639                              <1>         ;beq    1f / yes, no characters to output
  4640                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4641                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4642                              <1>         ;br     1b / try to calm it down again
  4643                              <1> ;1:
  4644                              <1>         ;mov    (sp)+,r1
  4645                              <1>         ;mov    (sp)+,r2 / restore registers
  4646                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4647                              <1>         ;beq    1f / if 0, 1f
  4648                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4649                              <1>         ;                   / control status register
  4650                              <1> ;1:
  4651                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4652                              <1>         ;beq    1f / if 0 1f
  4653                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4654                              <1> 	;		    / control status reg
  4655                              <1> ;1:
  4656                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4657                              <1>         ;jmp     sysret2 / return to user
  4658                              <1> 
  4659                              <1> sysgtty: ; < get tty status >
  4660                              <1> 	; 26/02/2022
  4661                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4662                              <1> 	;	    ((32 bit reg push/pop))
  4663                              <1> 	; 23/11/2015
  4664                              <1> 	; 29/10/2015
  4665                              <1> 	; 17/10/2015
  4666                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4667                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4668                              <1> 	;
  4669                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4670                              <1> 	; It stores in the three words addressed by it's argument
  4671                              <1> 	; the status of the typewriter whose file descriptor
  4672                              <1> 	; in (u.r0).
  4673                              <1> 	;
  4674                              <1> 	; Calling sequence:
  4675                              <1> 	;	sysgtty; arg
  4676                              <1> 	; Arguments:
  4677                              <1> 	;	arg - address of 3 words destination of the status
  4678                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4679                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4680                              <1> 	; ...............................................................
  4681                              <1> 	;	
  4682                              <1> 	; Retro UNIX 8086 v1 modification: 
  4683                              <1> 	;	'sysgtty' system call will return status of tty
  4684                              <1> 	;	(keyboard, serial port and video page status)
  4685                              <1> 	;	 in following manner:
  4686                              <1> 	;
  4687                              <1> 	; Inputs:
  4688                              <1> 	;	BX = 0 --> means 
  4689                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4690                              <1> 	;	                 for (current) process
  4691                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4692                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4693                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4694                              <1> 	;	     CH > 0 -->	tty number + 1
  4695                              <1> 	;
  4696                              <1> 	;	BX > 0 --> points to name of tty
  4697                              <1> 	;	     CL = 0 --> return keyboard status
  4698                              <1> 	;	     CL = 1 --> return video page status
  4699                              <1> 	;	     CH = undefined		 
  4700                              <1> 	;
  4701                              <1> 	; Outputs:
  4702                              <1> 	;	cf = 0 ->
  4703                              <1> 	;
  4704                              <1> 	;	     AL = tty number from 0 to 9
  4705                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4706                              <1> 	;	     AH = 0 if the tty is free/unused
  4707                              <1> 	;	     AH = the process number of the caller 
  4708                              <1>  	;	     AH = FFh if the tty is locked by another process
  4709                              <1> 	;
  4710                              <1> 	;	  (if calling is for serial port status)
  4711                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4712                              <1> 	;		  (BH = modem status, BL = Line status)
  4713                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4714                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4715                              <1> 	;
  4716                              <1> 	;	  (if calling is for keyboard status)
  4717                              <1> 	;	     BX = current character in tty/keyboard buffer
  4718                              <1> 	;		  (BH = scan code, BL = ascii code)
  4719                              <1> 	;		  (BX=0 if there is not a waiting character)
  4720                              <1> 	;	     CX  is undefined
  4721                              <1> 	;
  4722                              <1> 	;	  (if calling is for video page status)	
  4723                              <1> 	;	     BX = cursor position on the video page
  4724                              <1> 	;		  if tty number < 8
  4725                              <1> 	;		  (BH = row, BL = column)
  4726                              <1> 	;	     CX = current character (in cursor position)
  4727                              <1> 	;		  on the video page of the tty 
  4728                              <1> 	;		  if tty number < 8
  4729                              <1> 	;		  (CH = color, CL = character)
  4730                              <1> 	;	
  4731                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4732                              <1> 	;
  4733                              <1> 	;	     AH = FFh if the caller is not owner of
  4734                              <1> 	;		  specified tty or console tty
  4735                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4736                              <1> 	;	     BX, CX are undefined if cf = 1
  4737                              <1> 	;
  4738                              <1> 	;	  (If tty number is 8 or 9)
  4739                              <1> 	;	     AL = tty number 
  4740                              <1> 	;	     AH = the process number of the caller 
  4741                              <1> 	;	     BX = serial port status
  4742                              <1> 	;  		 (BH = modem status, BL = Line status)
  4743                              <1> 	;	     CX = 0
  4744                              <1> 	;
  4745                              <1> 		
  4746                              <1> gtty:   ; get (requested) tty number
  4747                              <1> 	; 26/02/2022
  4748                              <1> 	; 17/10/2015
  4749                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4750                              <1> 	; 30/05/2013 - 12/07/2014
  4751                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4752                              <1> 	;
  4753                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4754                              <1> 	;
  4755                              <1> 	; 28/06/2015 (32 bit modifications)
  4756                              <1> 	; 16/01/2014
  4757 00003872 31C0                <1> 	xor 	eax, eax
  4758 00003874 6648                <1> 	dec	ax ; 17/10/2015
  4759 00003876 A3[EC640000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4760 0000387B 80F901              <1> 	cmp	cl, 1
  4761 0000387E 760F                <1> 	jna	short sysgtty_0
  4762                              <1> sysgtty_invp:
  4763                              <1> 	; 28/06/2015
  4764 00003880 C705[41650000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4764 00003888 0000                <1>
  4765 0000388A E93CF8FFFF          <1> 	jmp	error
  4766                              <1> sysgtty_0:	
  4767 0000388F 21DB                <1> 	and	ebx, ebx
  4768 00003891 742E                <1> 	jz	short sysgtty_1
  4769                              <1> 	;
  4770 00003893 891D[04650000]      <1> 	mov	[u.namep], ebx
  4771                              <1> 	;push	cx ; 23/11/2015
  4772 00003899 51                  <1> 	push	ecx ; 24/12/2021
  4773 0000389A E838070000          <1> 	call	namei
  4774 0000389F 59                  <1> 	pop	ecx
  4775                              <1> 	;pop	cx ; 23/11/2015
  4776 000038A0 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4777                              <1> 	;
  4778 000038A2 6683F801            <1> 	cmp	ax, 1
  4779 000038A6 7622                <1> 	jna	short sysgtty_2
  4780                              <1> 	; 26/02/2022
  4781 000038A8 20E4                <1> 	and	ah, ah
  4782 000038AA 7506                <1> 	jnz	short sysgtty_inv_dn
  4783                              <1> 	;sub	ax, 10
  4784 000038AC 2C0A                <1> 	sub	al, 10
  4785 000038AE 3C09                <1> 	cmp	al, 9
  4786                              <1> 	;cmp	ax, 9
  4787                              <1> 	;ja	short sysgtty_inv_dn
  4788                              <1> 	;mov	ch, al
  4789                              <1> 	;jmp	short sysgtty_4
  4790                              <1> 	; 23/11/2015
  4791 000038B0 7629                <1> 	jna	short sysgtty_4
  4792                              <1> sysgtty_inv_dn: 
  4793                              <1> 	; 28/06/2015
  4794                              <1> 	; Invalid device name (not a tty) ! error
  4795                              <1> 	; (Device is not a tty or device name not found)
  4796 000038B2 C705[41650000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4796 000038BA 0000                <1>
  4797 000038BC E90AF8FFFF          <1> 	jmp	error 
  4798                              <1> sysgtty_1:
  4799                              <1> 	; 16/01/2014
  4800 000038C1 80FD0A              <1> 	cmp	ch, 10
  4801 000038C4 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4802 000038C6 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4803 000038C8 790F                <1> 	jns	short sysgtty_3 ; not negative
  4804                              <1> 	;
  4805                              <1> sysgtty_2:
  4806                              <1> 	; get tty number of console tty
  4807 000038CA 8A25[3B650000]      <1> 	mov	ah, [u.uno]
  4808                              <1>  	; 28/06/2015
  4809 000038D0 0FB6DC              <1> 	movzx 	ebx, ah
  4810 000038D3 8AAB[43620000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4811                              <1> sysgtty_3:
  4812 000038D9 88E8                <1> 	mov	al, ch
  4813                              <1> sysgtty_4:
  4814 000038DB A2[EC640000]        <1> 	mov	[u.r0], al
  4815                              <1>  	; 28/06/2015
  4816                              <1> 	;cmp	al, 9
  4817                              <1> 	;ja	short sysgtty_invp
  4818 000038E0 8B2D[E8640000]      <1> 	mov	ebp, [u.usp]
  4819                              <1> 	; 23/11/2015
  4820 000038E6 20C9                <1> 	and	cl, cl
  4821 000038E8 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4822 000038EA 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4823 000038EC 722E                <1> 	jb	short sysgtty_6 ; video page status
  4824                              <1> 	; serial port status
  4825                              <1> 	; 12/07/2014
  4826                              <1> 	;mov	dx, 0
  4827                              <1> 	;je	short sysgtty_5
  4828                              <1> 	;inc	dl
  4829                              <1> ;sysgtty_5:
  4830                              <1> 	; 28/06/2015
  4831 000038EE 2C08                <1> 	sub	al, 8
  4832 000038F0 E88CF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4833                              <1> 	; AL = Line status, AH = Modem status
  4834 000038F5 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4835 000038F9 8A25[3B650000]      <1> 	mov	ah, [u.uno]
  4836 000038FF 8825[ED640000]      <1>         mov     [u.r0+1], ah
  4837                              <1> 	; 24/12/2021
  4838 00003905 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4839                              <1> 				; (in ECX)
  4840 0000390B A880                <1> 	test	al, 80h
  4841 0000390D 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4842 0000390F A801                <1> 	test	al, 1
  4843                              <1> 	;jz	sysret
  4844 00003911 7404                <1> 	jz	short sysgtty_10
  4845 00003913 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4846                              <1> sysgtty_10:
  4847 00003917 E9CFF7FFFF          <1> 	jmp	sysret
  4848                              <1> sysgtty_6:
  4849 0000391C A2[40650000]        <1> 	mov	[u.ttyn], al ; tty number
  4850                              <1> 	;movzx	ebx, al
  4851 00003921 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4852 00003923 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4853                              <1> 	; 22/04/2014 - 29/06/2015
  4854 00003925 81C3[74610000]      <1>         add     ebx, ttyl
  4855 0000392B 8A23                <1>  	mov	ah, [ebx]
  4856 0000392D 3A25[3B650000]      <1> 	cmp	ah, [u.uno]
  4857 00003933 7404                <1> 	je	short sysgtty_7
  4858 00003935 20E4                <1> 	and	ah, ah
  4859                              <1> 	;jz	short sysgtty_7
  4860 00003937 7506                <1> 	jnz	short sysgtty_8
  4861                              <1> 	;mov	ah, 0FFh
  4862                              <1> sysgtty_7:
  4863 00003939 8825[ED640000]      <1>         mov     [u.r0+1], ah
  4864                              <1> sysgtty_8:
  4865 0000393F 08C9                <1> 	or	cl, cl
  4866 00003941 7510                <1> 	jnz	short sysgtty_9
  4867 00003943 B001                <1> 	mov	al, 1  ; test a key is available
  4868 00003945 E8341C0000          <1> 	call	getc
  4869 0000394A 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4870 0000394E E998F7FFFF          <1> 	jmp	sysret
  4871                              <1> sysgtty_9:
  4872 00003953 8A1D[40650000]      <1> 	mov	bl, [u.ttyn]
  4873                              <1> 	; bl = video page number
  4874 00003959 E8911D0000          <1> 	call 	get_cpos
  4875                              <1> 	; dx = cursor position
  4876 0000395E 66895510            <1> 	mov	[ebp+16], dx ; bx
  4877                              <1> 	;mov	bl, [u.ttyn]
  4878                              <1> 	; bl = video page number
  4879 00003962 E8991D0000          <1> 	call	read_ac_current
  4880                              <1> 	; ax = character and attribute/color
  4881 00003967 66894518            <1> 	mov	[ebp+24], ax ; cx
  4882 0000396B E97BF7FFFF          <1> 	jmp	sysret
  4883                              <1> sysgtty_dnr_err:
  4884                              <1> 	; 'device not responding !' error	
  4885                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4886 00003970 C705[41650000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4886 00003978 0000                <1>
  4887 0000397A E94CF7FFFF          <1> 	jmp	error	
  4888                              <1> 
  4889                              <1> ; Original UNIX v1 'sysgtty' routine:
  4890                              <1> ; sysgtty:
  4891                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4892                              <1> 	;	       / r2 has destination
  4893                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4894                              <1> 	;                     / in 1st word of dest
  4895                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4896                              <1> 	;                     / in 2nd word of dest
  4897                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4898                              <1>         ;jmp    sysret2 / return to user
  4899                              <1> 	
  4900                              <1> ; Original UNIX v1 'gtty' routine:
  4901                              <1> ; gtty:
  4902                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4903                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4904                              <1>         ;jsr    r0,getf / get the i-number of the file
  4905                              <1>         ;tst    r1 / is it open for reading
  4906                              <1>         ;bgt    1f / yes
  4907                              <1>         ;neg    r1 / no, i-number is negative, 
  4908                              <1> 	;          / so make it positive
  4909                              <1> ;1:
  4910                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4911                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4912                              <1>         ;bhis   error9 / no, error
  4913                              <1>         ;asl    r1 / 0%2
  4914                              <1>         ;asl    r1 / 0%4 / yes
  4915                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4916                              <1> 	;	       ; / tty block
  4917                              <1>         ;mov    u.off,r2 / put argument in r2
  4918                              <1>         ;rts    r0 / return
  2115                                  %include 'u2.s'        ; 11/05/2015
  2116                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS2.INC
  2117                              <1> ; Last Modification: 15/05/2022
  2118                              <1> ; ----------------------------------------------------------------------------
  2119                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2120                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2121                              <1> ;
  2122                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2123                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2124                              <1> ; <Bell Laboratories (17/3/1972)>
  2125                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2126                              <1> ;
  2127                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2128                              <1> ;
  2129                              <1> ; ****************************************************************************
  2130                              <1> 
  2131                              <1> syslink:
  2132                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2133                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2134                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2135                              <1> 	;
  2136                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2137                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2138                              <1> 	; given to the entry that will go in the current directory.
  2139                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2140                              <1> 	; in the name 2 entry of current directory is the same
  2141                              <1> 	; i-number for the name 1 file.
  2142                              <1> 	;
  2143                              <1> 	; Calling sequence:
  2144                              <1> 	;	syslink; name 1; name 2
  2145                              <1> 	; Arguments:
  2146                              <1> 	;	name 1 - file name to which link will be created.
  2147                              <1> 	;	name 2 - name of entry in current directory that
  2148                              <1> 	;		 links to name 1.
  2149                              <1> 	; Inputs: -
  2150                              <1> 	; Outputs: -
  2151                              <1> 	; ...............................................................
  2152                              <1> 	;	
  2153                              <1> 	; Retro UNIX 8086 v1 modification: 
  2154                              <1> 	;       'syslink' system call has two arguments; so,
  2155                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2156                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2157                              <1> 	;
  2158                              <1> 		; / name1, name2
  2159                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2160 0000397F 891D[04650000]      <1> 	mov	[u.namep], ebx
  2161 00003985 51                  <1> 	push	ecx
  2162 00003986 E84C060000          <1> 	call	namei
  2163                              <1> 		; jsr r0,namei / find the i-number associated with
  2164                              <1> 			     ; / the 1st path name
  2165                              <1>      	;;and	ax, ax
  2166                              <1> 	;;jz	error ; File not found
  2167                              <1> 	;jc	error 
  2168                              <1> 		; br error9 / cannot be found
  2169 0000398B 730F                <1> 	jnc	short syslink0
  2170                              <1> 	;pop 	ecx
  2171                              <1> 	; 'file not found !' error
  2172 0000398D C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2172 00003995 0000                <1>
  2173 00003997 E92FF7FFFF          <1> 	jmp	error
  2174                              <1> syslink0:
  2175 0000399C E8460E0000          <1> 	call	iget
  2176                              <1> 		; jsr r0,iget / get the i-node into core
  2177 000039A1 8F05[04650000]      <1> 	pop	dword [u.namep] ; ecx
  2178                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2179                              <1> 	; 24/12/2021
  2180 000039A7 50                  <1> 	push	eax ; *
  2181                              <1> 	;push	ax
  2182                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2183                              <1> 			    ; / (a link to this file is to be created)
  2184                              <1> 	; 24/12/2021
  2185 000039A8 8A0D[D3640000]      <1> 	mov	cl, [cdev]
  2186 000039AE 51                  <1> 	push	ecx ; **
  2187                              <1> 	;push	word [cdev]
  2188                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2189 000039AF E852000000          <1> 	call	isdir
  2190                              <1> 		; jsr r0,isdir / is it a directory
  2191 000039B4 E81E060000          <1> 	call	namei
  2192                              <1> 		; jsr r0,namei / no, get i-number of name2
  2193                              <1> 	;jnc	error
  2194                              <1> 		; br .+4   / not found 
  2195                              <1> 			 ; / so r1 = i-number of current directory
  2196                              <1> 			 ; / ii = i-number of current directory
  2197                              <1> 		; br error9 / file already exists., error
  2198 000039B9 720F                <1> 	jc	short syslink1
  2199                              <1> 	; pop eax ; 24/12/2021
  2200                              <1> 	; pop eax
  2201                              <1> 	; 'file exists !' error
  2202 000039BB C705[41650000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2202 000039C3 0000                <1>
  2203 000039C5 E901F7FFFF          <1> 	jmp	error
  2204                              <1> syslink1:
  2205                              <1> 	;pop	cx
  2206                              <1> 	; 24/12/2021
  2207 000039CA 59                  <1> 	pop	ecx ; **
  2208                              <1> 	;cmp	cx, [cdev]
  2209 000039CB 3A0D[D3640000]      <1> 	cmp	cl, [cdev]
  2210                              <1> 	;jne	error
  2211                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2212                              <1> 			       ; / end of current directory
  2213                              <1> 	        ; bne error9
  2214 000039D1 740F                <1> 	je	short syslink2
  2215                              <1> 	; 'not same drive !' error
  2216 000039D3 C705[41650000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2216 000039DB 0000                <1>
  2217 000039DD E9E9F6FFFF          <1> 	jmp	error
  2218                              <1> syslink2:
  2219                              <1> 	;pop	eax ; 24/12/2021
  2220                              <1> 	;push	eax
  2221                              <1> 	; 24/12/2021
  2222 000039E2 8B0424              <1> 	mov	eax, [esp] ; *
  2223 000039E5 66A3[1E650000]      <1> 	mov	[u.dirbuf], ax
  2224                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2225 000039EB E89E000000          <1> 	call	mkdir
  2226                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2227                              <1> 		 	     ; / in current directory
  2228                              <1> 	; 24/12/2021
  2229 000039F0 58                  <1> 	pop	eax ; *
  2230                              <1> 	;pop	ax
  2231                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2232 000039F1 E8F10D0000          <1> 	call	iget
  2233                              <1> 		; jsr r0,iget / get i-node into core
  2234 000039F6 FE05[E6610000]      <1> 	inc	byte [i.nlks]
  2235                              <1> 		; incb i.nlks / add 1 to its number of links
  2236 000039FC E8F00E0000          <1> 	call	setimod
  2237                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2238 00003A01 E9E5F6FFFF          <1> 	jmp	sysret
  2239                              <1> 
  2240                              <1> isdir:
  2241                              <1> 	; 03/02/2022
  2242                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2243                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2244                              <1> 	;
  2245                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2246                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2247                              <1> 	;  called by syslink and sysunlink to make sure directories
  2248                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2249                              <1> 	; 'isdir' does not bother checking. The current i-node
  2250                              <1> 	;  is not disturbed.			
  2251                              <1> 	;		
  2252                              <1> 	; INPUTS ->
  2253                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2254                              <1> 	;    u.uid - user id
  2255                              <1> 	; OUTPUTS ->
  2256                              <1> 	;    r1 - contains current i-number upon exit
  2257                              <1> 	;    	 (current i-node back in core) 
  2258                              <1> 	;	
  2259                              <1> 	; ((AX = R1))
  2260                              <1> 	;
  2261                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2262                              <1> 	;
  2263                              <1> 
  2264                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2265                              <1> 	; / there is an error unless super user made the call
  2266                              <1> 	
  2267 00003A06 803D[38650000]00    <1> 	cmp	byte [u.uid], 0 
  2268                              <1> 		; tstb u.uid / super user
  2269 00003A0D 762B                <1> 	jna	short isdir1
  2270                              <1> 		; beq 1f / yes, don't care
  2271 00003A0F 66FF35[D0640000]    <1> 	push	word [ii]
  2272                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2273 00003A16 E8CC0D0000          <1> 	call	iget
  2274                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2275                              <1> 	; 03/02/2022
  2276 00003A1B F605[E5610000]40    <1> 	test	byte [i.flgs+1], 40h
  2277                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2278                              <1> 		; bit $40000,i.flgs / is it a directory
  2279                              <1> 	;jnz	error
  2280                              <1> 		; bne error9 / yes, error
  2281 00003A22 740F                <1> 	jz	short isdir0
  2282 00003A24 C705[41650000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2282 00003A2C 0000                <1>
  2283                              <1> 				; 'permission denied !' error
  2284                              <1> 	; pop	ax
  2285 00003A2E E998F6FFFF          <1> 	jmp	error	
  2286                              <1> isdir0:	
  2287 00003A33 6658                <1> 	pop	ax
  2288                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2289 00003A35 E8AD0D0000          <1> 	call	iget
  2290                              <1> 		; jsr r0,iget / get it back in
  2291                              <1> isdir1: ; 1:
  2292 00003A3A C3                  <1> 	retn
  2293                              <1> 		; rts r0
  2294                              <1> 
  2295                              <1> sysunlink:
  2296                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2297                              <1> 	; 04/12/2015 (14 byte file names)
  2298                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2299                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2300                              <1> 	;
  2301                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2302                              <1> 	; name from its directory. If this entry was the last link
  2303                              <1> 	; to the file, the contents of the file are freed and the
  2304                              <1> 	; file is destroyed. If, however, the file was open in any
  2305                              <1> 	; process, the actual destruction is delayed until it is 
  2306                              <1> 	; closed, even though the directory entry has disappeared.
  2307                              <1> 	; 
  2308                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2309                              <1> 	; does not exist or that its directory can not be written.
  2310                              <1> 	; Write permission is not required on the file itself.
  2311                              <1> 	; It is also illegal to unlink a directory (except for
  2312                              <1> 	; the superuser).
  2313                              <1> 	;
  2314                              <1> 	; Calling sequence:
  2315                              <1> 	;	sysunlink; name
  2316                              <1> 	; Arguments:
  2317                              <1> 	;	name - name of directory entry to be removed 
  2318                              <1> 	; Inputs: -
  2319                              <1> 	; Outputs: -
  2320                              <1> 	; ...............................................................
  2321                              <1> 	;				
  2322                              <1> 	; Retro UNIX 8086 v1 modification:
  2323                              <1> 	;	 The user/application program puts address of the name
  2324                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2325                              <1> 
  2326                              <1> 	; / name - remove link name
  2327 00003A3B 891D[04650000]      <1> 	mov	[u.namep], ebx
  2328                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2329 00003A41 E891050000          <1> 	call	namei
  2330                              <1> 		; jsr r0,namei / find the i-number associated 
  2331                              <1> 			     ; / with the path name
  2332                              <1> 	;jc	error
  2333                              <1> 		; br error9 / not found
  2334 00003A46 730F                <1> 	jnc	short sysunlink1
  2335                              <1> 	; 'file not found !' error
  2336 00003A48 C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2336 00003A50 0000                <1>
  2337 00003A52 E974F6FFFF          <1> 	jmp	error
  2338                              <1> sysunlink1:
  2339 00003A57 50                  <1> 	push	eax ; 24/12/2021
  2340                              <1> 	;push	ax
  2341                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2342 00003A58 E8A9FFFFFF          <1> 	call	isdir
  2343                              <1> 		; jsr r0,isdir / is it a directory
  2344                              <1> 	;xor 	ax, ax
  2345                              <1> 	; 24/12/2021
  2346 00003A5D 31C0                <1> 	xor	eax, eax
  2347 00003A5F 66A3[1E650000]      <1> 	mov	[u.dirbuf], ax ; 0
  2348                              <1> 		; clr u.dirbuf / no, clear the location that will
  2349                              <1> 			   ; / get written into the i-number portion
  2350                              <1> 			 ; / of the entry
  2351 00003A65 832D[08650000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2352                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2353 00003A6C E868000000          <1> 	call	wdir
  2354                              <1> 		; jsr r0,wdir / free the directory entry
  2355 00003A71 58                  <1> 	pop	eax ; 24/12/2021
  2356                              <1> 	;pop	ax
  2357                              <1> 		; mov (sp)+,r1 / get i-number back
  2358 00003A72 E8700D0000          <1> 	call	iget
  2359                              <1> 		; jsr r0,iget / get i-node
  2360 00003A77 E8750E0000          <1> 	call	setimod
  2361                              <1> 		; jsr r0,setimod / set modified flag
  2362 00003A7C FE0D[E6610000]      <1> 	dec	byte [i.nlks]
  2363                              <1> 		; decb i.nlks / decrement the number of links
  2364                              <1> 	; 24/12/2021
  2365 00003A82 7505                <1> 	jnz	short sysunlink_2
  2366                              <1> 	;jnz	sysret
  2367                              <1> 		; bgt sysret9 / if this was not the last link
  2368                              <1> 			    ; / to file return
  2369                              <1> 	; AX = r1 = i-number
  2370 00003A84 E8B3090000          <1> 	call	anyi
  2371                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2372                              <1> 			 ; / Then free contents of file and destroy it.
  2373                              <1> sysunlink_2:
  2374 00003A89 E95DF6FFFF          <1> 	jmp	sysret
  2375                              <1> 		; br sysret9
  2376                              <1> 
  2377                              <1> mkdir:
  2378                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2379                              <1> 	; 04/12/2015 (14 byte directory names)
  2380                              <1> 	; 12/10/2015
  2381                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2382                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2383                              <1> 	;
  2384                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2385                              <1> 	; by u.namep into the current directory.
  2386                              <1> 	;
  2387                              <1> 	; INPUTS ->
  2388                              <1> 	;    u.namep - points to a file name 
  2389                              <1> 	;	           that is about to be a directory entry.
  2390                              <1> 	;    ii - current directory's i-number.	
  2391                              <1> 	; OUTPUTS ->
  2392                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2393                              <1> 	;    u.off - points to entry to be filled 
  2394                              <1> 	;	     in the current directory		
  2395                              <1> 	;    u.base - points to start of u.dirbuf.
  2396                              <1> 	;    r1 - contains i-number of current directory 
  2397                              <1> 	;	
  2398                              <1> 	; ((AX = R1)) output
  2399                              <1> 	;
  2400                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2401                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2402                              <1> 	;
  2403                              <1> 
  2404                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2405 00003A8E 31C0                <1> 	xor 	eax, eax
  2406 00003A90 BF[20650000]        <1> 	mov     edi, u.dirbuf+2
  2407 00003A95 89FE                <1> 	mov	esi, edi
  2408 00003A97 AB                  <1> 	stosd
  2409 00003A98 AB                  <1> 	stosd
  2410                              <1> 	; 04/12/2015 (14 byte directory names)
  2411 00003A99 AB                  <1> 	stosd
  2412 00003A9A 66AB                <1> 	stosw
  2413                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2414 00003A9C 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2415                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2416                              <1> 	;mov 	ebp, [u.namep]
  2417 00003A9E E8B3060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2418                              <1> 		; esi = physical address (page start + offset)
  2419                              <1> 		; ecx = byte count in the page (1 - 4096)
  2420                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2421                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2422                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2423                              <1> mkdir_1: ; 1: 
  2424 00003AA3 45                  <1> 	inc	ebp ; 12/10/2015
  2425                              <1> 	;
  2426                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2427                              <1> 	 ; 01/08/2013
  2428 00003AA4 AC                  <1> 	lodsb
  2429                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2430 00003AA5 20C0                <1> 	and 	al, al
  2431 00003AA7 7426                <1> 	jz 	short mkdir_3 	  
  2432                              <1> 		; beq 1f / if null, done
  2433 00003AA9 3C2F                <1> 	cmp	al, '/'
  2434                              <1> 		; cmp r1,$'/ / is it a "/"?
  2435 00003AAB 7413                <1> 	je	short mkdir_err
  2436                              <1> 	;je	error
  2437                              <1> 		; beq error9 / yes, error
  2438                              <1> 	; 12/10/2015
  2439                              <1> 	;dec	cx
  2440 00003AAD 49                  <1> 	dec	ecx ; 24/12/2021
  2441 00003AAE 7505                <1> 	jnz	short mkdir_2
  2442                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2443 00003AB0 E8A7060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2444                              <1> 		; esi = physical address (page start + offset)
  2445                              <1> 		; ecx = byte count in the page
  2446                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2447                              <1> mkdir_2:
  2448 00003AB5 81FF[2E650000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2449                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2450                              <1> 				     ; / a char?
  2451 00003ABB 74E6                <1> 	je	short mkdir_1
  2452                              <1> 		; beq 1b / yes, go back
  2453 00003ABD AA                  <1> 	stosb
  2454                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2455 00003ABE EBE3                <1> 	jmp 	short mkdir_1
  2456                              <1> 		; br 1b / get next char
  2457                              <1> mkdir_err:
  2458                              <1> 	; 17/06/2015
  2459 00003AC0 C705[41650000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2459 00003AC8 0000                <1>
  2460 00003ACA E9FCF5FFFF          <1> 	jmp	error
  2461                              <1> 
  2462                              <1> mkdir_3: ; 1:
  2463 00003ACF A1[00650000]        <1> 	mov	eax, [u.dirp]
  2464 00003AD4 A3[08650000]        <1> 	mov	[u.off], eax
  2465                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2466                              <1> 				 ; / slot to u.off
  2467                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2468                              <1> 	; 29/04/2013
  2469 00003AD9 C705[0C650000]-     <1>         mov     dword [u.base], u.dirbuf
  2469 00003ADF [1E650000]          <1>
  2470                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2471 00003AE3 C705[10650000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2471 00003AEB 0000                <1>
  2472                              <1> 		; mov $10.,u.count / u.count = 10
  2473 00003AED 66A1[D0640000]      <1> 	mov	ax, [ii] 
  2474                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2475 00003AF3 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2476 00003AF5 E8C10D0000          <1> 	call 	access
  2477                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2478                              <1> 				 ; / for writing
  2479                              <1> 	; AX = i-number of current directory
  2480                              <1> 	; 01/08/2013
  2481 00003AFA FE05[53650000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2482                              <1> 	;call	writei
  2483                              <1> 	;	; jsr r0,writei / write into directory
  2484                              <1> 	;retn	
  2485                              <1> 	;	; rts r0
  2486                              <1> 	; 24/12/2021
  2487 00003B00 E9A8100000          <1> 	jmp	writei
  2488                              <1> 
  2489                              <1> sysexec:
  2490                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2491                              <1> 	; 03/02/2022
  2492                              <1> 	; 12/01/2022
  2493                              <1> 	; 08/01/2022
  2494                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2495                              <1> 	; 23/10/2015
  2496                              <1> 	; 19/10/2015
  2497                              <1> 	; 10/10/2015, 18/10/2015
  2498                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2499                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2500                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2501                              <1> 	; 24/06/2015, 25/06/2015
  2502                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2503                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2504                              <1> 	;
  2505                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2506                              <1> 	; pointed to by 'name' in the sysexec call. 
  2507                              <1> 	; 'sysexec' performs the following operations:
  2508                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2509                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2510                              <1> 	;    3. sets trap vectors to system routines.
  2511                              <1> 	;    4. loads arguments to be passed to executing file into
  2512                              <1> 	;	highest locations of user's core
  2513                              <1> 	;    5. puts pointers to arguments in locations immediately
  2514                              <1> 	;	following arguments.
  2515                              <1> 	;    6.	saves number of arguments in next location.
  2516                              <1> 	;    7. initializes user's stack area so that all registers
  2517                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2518                              <1> 	;	to core when 'sysret' restores registers 
  2519                              <1> 	;	and does an rti.
  2520                              <1> 	;    8. inializes u.r0 and u.sp
  2521                              <1> 	;    9. zeros user's core down to u.r0
  2522                              <1> 	;   10.	reads executable file from storage device into core
  2523                              <1> 	;	starting at location 'core'.
  2524                              <1> 	;   11.	sets u.break to point to end of user's code with
  2525                              <1> 	;	data area appended.
  2526                              <1> 	;   12.	calls 'sysret' which returns control at location
  2527                              <1> 	;	'core' via 'rti' instruction. 		  		
  2528                              <1> 	;
  2529                              <1> 	; Calling sequence:
  2530                              <1> 	;	sysexec; namep; argp
  2531                              <1> 	; Arguments:
  2532                              <1> 	;	namep - points to pathname of file to be executed
  2533                              <1> 	;	argp  - address of table of argument pointers
  2534                              <1> 	;	argp1... argpn - table of argument pointers
  2535                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2536                              <1> 	; Inputs: (arguments)
  2537                              <1> 	; Outputs: -	
  2538                              <1> 	; ...............................................................
  2539                              <1> 	;
  2540                              <1> 	; Retro UNIX 386 v1 modification: 
  2541                              <1> 	;	User application runs in it's own virtual space 
  2542                              <1> 	;	which is izolated from kernel memory (and other
  2543                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2544                              <1> 	;	privilige mode. Virtual start address is always 0.
  2545                              <1> 	;	User's core memory starts at linear address 400000h
  2546                              <1> 	;	(the end of the 1st 4MB).
  2547                              <1> 	;
  2548                              <1> 	; Retro UNIX 8086 v1 modification: 
  2549                              <1> 	;	user/application segment and system/kernel segment
  2550                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2551                              <1> 	;	are different (user's registers are saved to 
  2552                              <1> 	;	and then restored from system's stack.)
  2553                              <1> 	;
  2554                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2555                              <1> 	;	      arguments which were in these registers;
  2556                              <1> 	;	      but, it returns by putting the 1st argument
  2557                              <1> 	;	      in 'u.namep' and the 2nd argument
  2558                              <1> 	;	      on top of stack. (1st argument is offset of the
  2559                              <1> 	;	      file/path name in the user's program segment.)		 	
  2560                              <1> 	
  2561                              <1> 	;call	arg2
  2562                              <1> 	; * name - 'u.namep' points to address of file/path name
  2563                              <1> 	;          in the user's program segment ('u.segmnt')
  2564                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2565                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2566                              <1> 	;          which is on top of stack.
  2567                              <1> 	;
  2568                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2569                              <1> 
  2570                              <1> 	; 23/06/2015 (32 bit modifications)
  2571                              <1> 
  2572 00003B05 891D[04650000]      <1> 	mov	[u.namep], ebx ; argument 1
  2573                              <1>         ; 18/10/2015
  2574 00003B0B 890D[6C650000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2575 00003B11 E8C1040000          <1> 	call	namei
  2576                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2577                              <1> 			     ; / named in sysexec call in r1
  2578                              <1> 	;jc	error
  2579                              <1> 		; br error9
  2580 00003B16 731E                <1> 	jnc	short sysexec_0
  2581                              <1> 	;
  2582                              <1> 	; 'file not found !' error
  2583 00003B18 C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2583 00003B20 0000                <1>
  2584 00003B22 E9A4F5FFFF          <1> 	jmp	error 
  2585                              <1> sysexec_not_exf:
  2586                              <1> 	; 'not executable file !' error
  2587 00003B27 C705[41650000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2587 00003B2F 0000                <1>
  2588 00003B31 E995F5FFFF          <1> 	jmp	error 
  2589                              <1> sysexec_0:
  2590 00003B36 E8AC0C0000          <1> 	call	iget
  2591                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2592                              <1> 	; 24/12/2021
  2593 00003B3B F605[E4610000]10    <1> 	test	byte [i.flgs], 10h
  2594                              <1> 	;test	word [i.flgs], 10h
  2595                              <1> 	;	; bit $20,i.flgs / is file executable
  2596 00003B42 74E3                <1> 	jz	short sysexec_not_exf
  2597                              <1> 	;jz	error
  2598                              <1> 		; beq error9
  2599                              <1> 	;;
  2600 00003B44 E802150000          <1> 	call	iopen
  2601                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2602                              <1> 			     ; / given in r1 (opens file)
  2603                              <1> 	; AX = i-number of the file
  2604                              <1> 	; 24/12/2021
  2605 00003B49 F605[E4610000]20    <1> 	test	byte [i.flgs], 20h
  2606                              <1> 	;test	word [i.flgs], 20h
  2607                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2608 00003B50 7415                <1> 	jz	short sysexec_1
  2609                              <1> 		; beq 1f
  2610 00003B52 803D[38650000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2611                              <1> 		; tstb u.uid / test user id
  2612 00003B59 760C                <1> 	jna	short sysexec_1
  2613                              <1> 		; beq 1f / super user
  2614 00003B5B 8A0D[E7610000]      <1> 	mov	cl, [i.uid]
  2615 00003B61 880D[38650000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2616                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2617                              <1> 				 ; / as process user id
  2618                              <1> sysexec_1:
  2619                              <1> 	; 03/02/2022
  2620                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2621                              <1> 	; 18/10/2215
  2622                              <1> 	; 10/10/2015
  2623                              <1> 	; 21/07/2015, 24/07/2015
  2624                              <1> 	; 24/06/2015, 25/06/2015
  2625                              <1>         ; Moving arguments to the end of [u.upage]
  2626                              <1> 	; (by regarding page borders in user's memory space)
  2627                              <1> 	;
  2628                              <1> 	; 10/10/2015
  2629                              <1> 	; 21/07/2015
  2630 00003B67 89E5                <1> 	mov	ebp, esp ; (**)
  2631                              <1> 	; 18/10/2015
  2632 00003B69 89EF                <1> 	mov 	edi, ebp
  2633 00003B6B B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2634                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2635 00003B70 29CF                <1> 	sub	edi, ecx
  2636 00003B72 89FC                <1> 	mov	esp, edi
  2637 00003B74 31C0                <1> 	xor	eax, eax
  2638 00003B76 A3[14650000]        <1> 	mov 	[u.nread], eax ; 0
  2639                              <1> 	; 12/01/2022
  2640                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2641                              <1> 	; may leave it with any value after an error))
  2642                              <1> 	;mov	[argc], ax
  2643 00003B7B A2[6A650000]        <1> 	mov	[argc], al ; 0
  2644                              <1> 	;
  2645 00003B80 49                  <1> 	dec	ecx ; 256 - 1
  2646 00003B81 890D[10650000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2647                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2648                              <1> sysexec_2:
  2649 00003B87 8B35[6C650000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2650 00003B8D E863020000          <1> 	call	get_argp
  2651                              <1> 	;mov	ecx, 4 
  2652                              <1> 	; 03/02/2022
  2653 00003B92 31C9                <1> 	xor	ecx, ecx
  2654 00003B94 B104                <1> 	mov	cl, 4
  2655                              <1> sysexec_3:
  2656 00003B96 21C0                <1> 	and	eax, eax
  2657 00003B98 7455                <1> 	jz	short sysexec_6
  2658                              <1> 	; 18/10/2015
  2659 00003B9A 010D[6C650000]      <1> 	add	[argv], ecx ; 4
  2660                              <1> 	;inc	word [argc]
  2661                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2662 00003BA0 FE05[6A650000]      <1> 	inc	byte [argc]
  2663                              <1> 	;
  2664 00003BA6 A3[0C650000]        <1> 	mov	[u.base], eax
  2665                              <1>  	; 23/10/2015
  2666 00003BAB 66C705[51650000]00- <1> 	mov	word [u.pcount], 0
  2666 00003BB3 00                  <1>
  2667                              <1> sysexec_4:
  2668 00003BB4 E826120000          <1> 	call	cpass ; get a character from user's core memory
  2669 00003BB9 750B                <1>         jnz	short sysexec_5
  2670                              <1> 		; (max. 255 chars + null)
  2671                              <1> 	; 18/10/2015
  2672 00003BBB 28C0                <1> 	sub 	al, al
  2673 00003BBD AA                  <1> 	stosb
  2674 00003BBE FF05[14650000]      <1> 	inc	dword [u.nread]
  2675 00003BC4 EB29                <1> 	jmp	short sysexec_6
  2676                              <1> sysexec_5:
  2677 00003BC6 AA                  <1> 	stosb
  2678 00003BC7 20C0                <1> 	and 	al, al
  2679 00003BC9 75E9                <1> 	jnz	short sysexec_4
  2680                              <1> 	;mov	ecx, 4
  2681                              <1> 	; 24/12/2021
  2682 00003BCB 29C9                <1> 	sub	ecx, ecx
  2683 00003BCD B104                <1> 	mov	cl, 4
  2684                              <1> 	;cmp	[ncount], ecx ; 4
  2685                              <1> 	; 24/12/2021
  2686 00003BCF 66390D[68650000]    <1> 	cmp	[ncount], cx ; 4
  2687 00003BD6 72AF                <1> 	jb	short sysexec_2
  2688 00003BD8 8B35[64650000]      <1> 	mov	esi, [nbase]
  2689 00003BDE 010D[64650000]      <1> 	add	[nbase], ecx ; 4	
  2690 00003BE4 66290D[68650000]    <1> 	sub	[ncount], cx 
  2691 00003BEB 8B06                <1> 	mov	eax, [esi]
  2692 00003BED EBA7                <1> 	jmp	short sysexec_3
  2693                              <1> sysexec_6:
  2694                              <1> 	; 18/10/2015
  2695                              <1> 	; argument list transfer from user's core memory to
  2696                              <1> 	; kernel stack frame is OK here.
  2697                              <1> 	; [u.nread] = ; argument list length
  2698                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2699                              <1> 	;
  2700                              <1> 	; 18/10/2015
  2701                              <1> 	; 24/07/2015
  2702                              <1>         ; 21/07/2015
  2703                              <1> 	; 02/07/2015
  2704                              <1> 	; 25/06/2015
  2705                              <1> 	; 24/06/2015
  2706                              <1> 	; 23/06/2015
  2707                              <1> 	;
  2708 00003BEF 8B1D[49650000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2709 00003BF5 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2710 00003BF7 740A                <1> 	jz	short sysexec_7
  2711 00003BF9 A1[45650000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2712 00003BFE E8EEE8FFFF          <1> 	call	deallocate_page_dir
  2713                              <1> sysexec_7:
  2714 00003C03 E81EE8FFFF          <1> 	call	make_page_dir
  2715                              <1> 	;jc	short sysexec_14
  2716                              <1> 	;jc	panic  ; allocation error 
  2717                              <1> 		       ; after a deallocation would be nonsence !?
  2718                              <1> 	; 08/01/2022
  2719 00003C08 7243                <1> 	jc	short sysexec_panic
  2720                              <1> 
  2721                              <1> 	; 24/07/2015
  2722                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2723                              <1> 	;     of the user's page directory
  2724                              <1> 	;     (It is needed for interrupts!)
  2725                              <1> 	; 18/10/2015
  2726 00003C0A 8B15[28610000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2727 00003C10 8B02                <1> 	mov	eax, [edx] ; physical address of
  2728                              <1> 			   ; kernel's first page table (1st 4 MB)
  2729                              <1> 			   ; (PDE 0 of kernel's page directory)
  2730 00003C12 8B15[45650000]      <1> 	mov 	edx, [u.pgdir]
  2731 00003C18 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2732                              <1> 	;
  2733                              <1> 	; 20/07/2015
  2734 00003C1A BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2735                              <1> 	; 18/10/2015
  2736 00003C1F BE[5C650000]        <1> 	mov	esi, pcore ; physical start address
  2737                              <1> sysexec_8:	
  2738 00003C24 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2739 00003C29 E816E8FFFF          <1> 	call	make_page_table
  2740                              <1> 	;jc	panic
  2741                              <1> 	; 24/12/2021
  2742 00003C2E 721D                <1> 	jc	short sysexec_panic
  2743                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2744 00003C30 E81DE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2745                              <1> 	;jc	panic
  2746                              <1> 	; 24/12/2021
  2747 00003C35 7216                <1> 	jc	short sysexec_panic
  2748                              <1> 	;
  2749 00003C37 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2750                              <1> 	; ebx = virtual address (24/07/2015)
  2751                              <1> 	; 24/12/2021
  2752                              <1> 	;call 	add_to_swap_queue
  2753                              <1> 	; 18/10/2015
  2754 00003C39 81FE[60650000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2755 00003C3F 7411                <1> 	je	short sysexec_9 ; yes
  2756 00003C41 BE[60650000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2757                              <1> 	; 20/07/2015
  2758 00003C46 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2759                              <1> 	; ebx = virtual end address + segment base address - 4K
  2760 00003C4B EBD7                <1>         jmp     short sysexec_8
  2761                              <1> 
  2762                              <1> sysexec_panic:
  2763                              <1> 	; 26/03/2021
  2764 00003C4D E93BEDFFFF          <1> 	jmp	panic
  2765                              <1> 
  2766                              <1> sysexec_9:
  2767                              <1> 	; 18/10/2015
  2768                              <1> 	; 26/08/2015
  2769                              <1> 	; 25/06/2015
  2770                              <1> 	; move arguments from kernel stack to [ecore]
  2771                              <1> 	; (argument list/line will be copied from kernel stack
  2772                              <1> 	; frame to the last (stack) page of user's core memory)
  2773                              <1> 	; 18/10/2015
  2774 00003C52 8B3D[60650000]      <1> 	mov	edi, [ecore]
  2775 00003C58 81C700100000        <1> 	add	edi, PAGE_SIZE
  2776                              <1> 	;movzx	eax, word [argc]
  2777                              <1> 	; 12/01/2022
  2778 00003C5E 31C0                <1> 	xor	eax, eax
  2779 00003C60 A0[6A650000]        <1> 	mov	al, [argc]
  2780 00003C65 08C0                <1> 	or	al, al
  2781                              <1> 	;or	eax, eax
  2782 00003C67 7509                <1> 	jnz	short sysexec_10
  2783 00003C69 89FB                <1> 	mov 	ebx, edi
  2784 00003C6B 83EB04              <1> 	sub	ebx, 4 
  2785 00003C6E 8903                <1> 	mov	[ebx], eax ; 0
  2786 00003C70 EB43                <1> 	jmp 	short sysexec_13
  2787                              <1> sysexec_10:
  2788 00003C72 8B0D[14650000]      <1> 	mov	ecx, [u.nread]
  2789                              <1> 	;mov 	esi, [argv]
  2790 00003C78 89E6                <1> 	mov	esi, esp ; start address of argument list
  2791 00003C7A 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2792                              <1> 
  2793                              <1> 	;;;;
  2794                              <1> 	; 09/05/2022
  2795                              <1> 	; (move edi -backward- to dword boundary)
  2796                              <1> 	; ((this will prevent 'general protection fault' error
  2797                              <1> 	;  as result of a lodsd or dword move instruction
  2798                              <1> 	;  at the end of argument list))
  2799 00003C7C 83EF03              <1> 	sub	edi, 3
  2800 00003C7F 83E7FC              <1> 	and	edi, ~3 ; (*)
  2801                              <1> 	;;;
  2802                              <1> 
  2803 00003C82 89C2                <1> 	mov	edx, eax
  2804                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2805 00003C84 FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2806 00003C86 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2807                              <1> 	; edx <= 128
  2808 00003C89 89FB                <1> 	mov	ebx, edi
  2809                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2810                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2811 00003C8B 29D3                <1> 	sub 	ebx, edx
  2812 00003C8D 89FA                <1> 	mov	edx, edi
  2813 00003C8F F3A4                <1> 	rep	movsb
  2814 00003C91 89D6                <1> 	mov 	esi, edx
  2815 00003C93 89DF                <1> 	mov 	edi, ebx
  2816 00003C95 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2817 00003C9A 2B15[60650000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2818 00003CA0 AB                  <1> 	stosd	; eax = argument count	
  2819                              <1> sysexec_11:
  2820 00003CA1 89F0                <1> 	mov	eax, esi
  2821 00003CA3 01D0                <1> 	add	eax, edx
  2822 00003CA5 AB                  <1> 	stosd  ; eax = virtual address
  2823 00003CA6 FE0D[6A650000]      <1> 	dec	byte [argc]
  2824 00003CAC 7407                <1> 	jz	short sysexec_13
  2825                              <1> sysexec_12:
  2826 00003CAE AC                  <1> 	lodsb
  2827 00003CAF 20C0                <1> 	and	al, al
  2828 00003CB1 75FB                <1> 	jnz	short sysexec_12
  2829 00003CB3 EBEC                <1> 	jmp	short sysexec_11
  2830                              <1> 	;
  2831                              <1> 	; 1:
  2832                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2833                              <1> 			     ; / pointers to arguments to be passed
  2834                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2835                              <1> 			      ; / u.quit = 1 take quit
  2836                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2837                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2838                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2839                              <1> 			       ; / system routine
  2840                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2841                              <1> 			       ; / set to take system routine
  2842                              <1> 		; mov $sstack,sp / stack space used during swapping
  2843                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2844                              <1> 		; mov $ecore,r5 / r5 has end of core
  2845                              <1> 		; mov $core,r4 / r4 has start of users core
  2846                              <1> 		; mov r4,u.base / u.base has start of users core
  2847                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2848                              <1> 	; 1:
  2849                              <1> 		; tst (r2)+ / argument char = "nul"
  2850                              <1> 		; bne 1b
  2851                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2852                              <1> 			  ; / end of argument pointer list
  2853                              <1> 	; 1:
  2854                              <1> 	     ; / move arguments to bottom of users core
  2855                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2856                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2857                              <1> 			    ; / ptr list
  2858                              <1> 		; blo 1f / branch to 1f when all arguments
  2859                              <1> 		       ; / are moved
  2860                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2861                              <1> 	; 2:
  2862                              <1> 		; tstb (r3)+
  2863                              <1> 		; bne 2b / scan argument for \0 (nul)
  2864                              <1> 
  2865                              <1> 	; 2:
  2866                              <1> 		; movb -(r3),-(r5) / move argument char 
  2867                              <1> 				 ; / by char starting at "ecore"
  2868                              <1> 		; cmp r3,(r2) / moved all characters in 
  2869                              <1> 			    ; / this argument
  2870                              <1> 		; bhi 2b / branch 2b if not
  2871                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2872                              <1> 			     ; / r5 has pointer to nth arg
  2873                              <1> 		; br 1b / string
  2874                              <1> 	; 1:
  2875                              <1> 		; clrb -(r5)
  2876                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2877                              <1> 			; / last word of argument strings
  2878                              <1> 		; mov $core,r2
  2879                              <1> 	
  2880                              <1> 	; 1: / move argument pointers into core following 
  2881                              <1> 	      ; / argument strings
  2882                              <1> 		; cmp r2,r4
  2883                              <1> 		; bhis 1f / branch to 1f when all pointers
  2884                              <1> 			; / are moved
  2885                              <1> 		; mov (r2)+,-(r5)
  2886                              <1> 		; br 1b
  2887                              <1> 	; 1:
  2888                              <1> 		; sub $core,r4 / gives number of arguments *2
  2889                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2890                              <1> 		       ; / the number of args stored
  2891                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2892                              <1> 			     ; / of the argument pointers
  2893                              <1> sysexec_13:
  2894                              <1> 	; 19/10/2015
  2895                              <1> 	; 18/10/2015
  2896                              <1> 	; 29/07/2015
  2897                              <1> 	; 25/07/2015
  2898                              <1> 	; 24/07/2015
  2899                              <1> 	; 20/07/2015
  2900                              <1> 	; 25/06/2015
  2901                              <1> 	; 24/06/2015
  2902                              <1> 	; 23/06/2015
  2903                              <1> 	;
  2904                              <1> 	; moving arguments to [ecore] is OK here..
  2905                              <1> 	; 18/10/2015
  2906 00003CB5 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2907                              <1> 	; ebx = beginning addres of argument list pointers
  2908                              <1> 	;	in user's stack
  2909                              <1> 	; 19/10/2015
  2910 00003CB7 2B1D[60650000]      <1> 	sub 	ebx, [ecore]
  2911 00003CBD 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2912                              <1> 			; end of core - 4096 (last page)
  2913                              <1> 			; (virtual address)
  2914 00003CC3 891D[6C650000]      <1> 	mov	[argv], ebx
  2915 00003CC9 891D[18650000]      <1> 	mov	[u.break], ebx ; available user memory
  2916                              <1> 	;
  2917 00003CCF 29C0                <1> 	sub	eax, eax
  2918 00003CD1 C705[10650000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2918 00003CD9 0000                <1>
  2919                              <1> 		; mov $14,u.count
  2920 00003CDB C705[FC640000]-     <1> 	mov	dword [u.fofp], u.off
  2920 00003CE1 [08650000]          <1>
  2921                              <1> 		; mov $u.off,u.fofp
  2922 00003CE5 A3[08650000]        <1> 	mov	[u.off], eax ; 0
  2923                              <1> 		; clr u.off / set offset in file to be read to zero
  2924                              <1> 	; 25/07/2015
  2925 00003CEA A3[0C650000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2926                              <1> 	; 25/06/2015 
  2927 00003CEF 66A1[D0640000]      <1> 	mov	ax, [ii]
  2928                              <1> 	; AX = i-number of the executable file
  2929 00003CF5 E8C10C0000          <1> 	call	readi
  2930                              <1> 		; jsr r0,readi / read in first six words of 
  2931                              <1> 			; / user's file, starting at $core
  2932                              <1> 		; mov sp,r5 / put users stack address in r5
  2933                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2934                              <1> 				; / from r5 (leaves number of words
  2935                              <1> 				; / less 26 available for
  2936                              <1> 			     	; / program in user core
  2937                              <1> 		; mov r5,u.count /
  2938                              <1> 	; 25/06/2015
  2939 00003CFA 8B0D[18650000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2940 00003D00 890D[10650000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2941                              <1> 	;
  2942 00003D06 8B0D[14650000]      <1> 	mov	ecx, [u.nread]
  2943 00003D0C 890D[18650000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2944 00003D12 80F920              <1> 	cmp	cl, 32
  2945 00003D15 7540                <1>         jne     short sysexec_15
  2946                              <1> 	;:
  2947                              <1> 	; 25/06/2015
  2948                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2949                              <1> 	; 18/10/2015
  2950 00003D17 8B35[5C650000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2951                              <1> 		             ; (phys. start addr. of the exec. file)
  2952 00003D1D AD                  <1> 	lodsd
  2953 00003D1E 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2954 00003D22 7533                <1> 	jne	short sysexec_15
  2955                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2956                              <1> 			      ; / if file is standard a.out format
  2957                              <1> 		; bne 1f / branch, if not standard format
  2958 00003D24 AD                  <1> 	lodsd
  2959 00003D25 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2960 00003D27 AD                  <1> 	lodsd
  2961 00003D28 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2962                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2963                              <1> 		              ; / number of bytes in program text	
  2964                              <1> 		; sub $14,r5 / subtract 12
  2965 00003D2A 89CB                <1> 	mov	ebx, ecx
  2966                              <1> 	;
  2967                              <1> 	; 25/06/2015
  2968                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2969                              <1> 	;	and SINGLIX operating systems (as code template).
  2970                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2971                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2972                              <1> 	;	Overrun is not possible for current version. 	
  2973                              <1> 	;
  2974 00003D2C AD                  <1> 	lodsd	
  2975 00003D2D 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2976 00003D2F 3B1D[10650000]      <1> 	cmp	ebx, [u.count]
  2977 00003D35 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2978                              <1> 	;
  2979                              <1> 	; 24/07/2015
  2980                              <1> 	; add bss section size to [u.break]
  2981 00003D37 0105[18650000]      <1> 	add 	[u.break], eax
  2982                              <1> 	;
  2983 00003D3D 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2984                              <1> 	;cmp	ecx, [u.count]
  2985                              <1> 	;jnb	short sysexec_16
  2986                              <1> 		; cmp r5,u.count /
  2987                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2988 00003D40 890D[10650000]      <1> 	mov	[u.count], ecx ; required read count
  2989                              <1> 		; mov r5,u.count
  2990                              <1> 	;
  2991 00003D46 EB2A                <1> 	jmp	short sysexec_16
  2992                              <1> 	;
  2993                              <1> sysexec_14:
  2994                              <1> 	; 23/06/2015
  2995                              <1> 	; insufficient (out of) memory
  2996 00003D48 C705[41650000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2996 00003D50 0000                <1>
  2997 00003D52 E974F3FFFF          <1> 	jmp	error
  2998                              <1> 	;
  2999                              <1> sysexec_15:
  3000                              <1> 	; 25/06/2015
  3001 00003D57 0FB715[E8610000]    <1>         movzx   edx, word [i.size] ; file size
  3002 00003D5E 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  3003 00003D60 7627                <1> 	jna	short sysexec_17 ; no need to next read
  3004 00003D62 01D1                <1> 	add	ecx, edx ; [i.size]
  3005 00003D64 3B0D[10650000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  3006 00003D6A 77DC                <1> 	ja	short sysexec_14
  3007 00003D6C 8915[10650000]      <1> 	mov	[u.count], edx
  3008                              <1> sysexec_16:
  3009 00003D72 66A1[D0640000]      <1> 	mov	ax, [ii] ; i-number
  3010 00003D78 E83E0C0000          <1> 	call	readi
  3011                              <1> 		; add core+10,u.nread / add size of user data area 
  3012                              <1> 		                    ; / to u.nread
  3013                              <1> 		; br 2f
  3014                              <1> 	; 1:
  3015                              <1> 		; jsr r0,readi / read in rest of file
  3016                              <1> 	; 2:
  3017 00003D7D 8B0D[14650000]      <1> 	mov	ecx, [u.nread]
  3018 00003D83 010D[18650000]      <1> 	add	[u.break], ecx
  3019                              <1> 		; mov u.nread,u.break / set users program break to end of 
  3020                              <1> 				    ; / user code
  3021                              <1> 		; add $core+14,u.break / plus data area
  3022                              <1> sysexec_17: ; 20/07/2015
  3023                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3024                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3025                              <1> 	;;mov	ax, [ii] ; i-number
  3026                              <1> 	;call	iclose
  3027                              <1> 	;	; jsr r0,iclose / does nothing
  3028 00003D89 31C0                <1>         xor     eax, eax
  3029 00003D8B FEC0                <1> 	inc	al
  3030 00003D8D 66A3[30650000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3031 00003D93 66A3[32650000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3032                              <1> 	; 02/07/2015
  3033 00003D99 833D[49650000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  3034 00003DA0 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3035                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3036 00003DA2 8B15[28610000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3037 00003DA8 8915[49650000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  3038                              <1> sysexec_18:
  3039                              <1> 	; 18/10/2015
  3040                              <1> 	; 05/08/2015
  3041                              <1> 	; 29/07/2015
  3042 00003DAE 8B2D[6C650000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3043                              <1> 			    ; list pointers (argument count)
  3044 00003DB4 FA                  <1> 	cli
  3045 00003DB5 8B25[C4600000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3046                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3047                              <1> 			    ; for this process	 
  3048                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3049                              <1> 	;xor	eax, eax ; 0
  3050 00003DBB FEC8                <1> 	dec	al ; eax = 0
  3051 00003DBD 66BA2300            <1> 	mov	dx, UDATA
  3052 00003DC1 6652                <1> 	push	dx  ; user's stack segment
  3053 00003DC3 55                  <1> 	push	ebp ; user's stack pointer
  3054                              <1> 		    ; (points to number of arguments)
  3055 00003DC4 FB                  <1> 	sti
  3056 00003DC5 9C                  <1> 	pushfd	; EFLAGS
  3057                              <1> 		; Set IF for enabling interrupts in user mode	
  3058                              <1> 	;or	dword [esp], 200h 
  3059                              <1> 	;
  3060                              <1> 	;mov	bx, UCODE
  3061                              <1> 	;push	bx ; user's code segment
  3062 00003DC6 6A1B                <1> 	push	UCODE
  3063                              <1> 	;push	0
  3064 00003DC8 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3065                              <1> 		; clr -(r5) / popped into ps when rti in 
  3066                              <1> 			  ; / sysrele is executed
  3067                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3068                              <1> 		                ; / in sysrele is executed
  3069                              <1> 		;mov r5,0f / load second copyz argument
  3070                              <1> 		;tst -(r5) / decrement r5
  3071 00003DC9 8925[E4640000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3072                              <1> 	; 05/08/2015
  3073                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3074                              <1> 	; ('push dx' would cause to general protection fault, 
  3075                              <1> 	; after 'pop ds' etc.)
  3076                              <1> 	;
  3077                              <1> 	;; push dx ; ds (UDATA)
  3078                              <1> 	;; push dx ; es (UDATA)
  3079                              <1> 	;; push dx ; fs (UDATA)
  3080                              <1> 	;; push dx ; gs (UDATA)
  3081                              <1> 	;
  3082                              <1> 	; This is a trick to prevent general protection fault
  3083                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3084 00003DCF 8EC2                <1> 	mov 	es, dx ; UDATA
  3085 00003DD1 06                  <1> 	push 	es ; ds (UDATA)
  3086 00003DD2 06                  <1> 	push 	es ; es (UDATA)
  3087 00003DD3 06                  <1> 	push 	es ; fs (UDATA)
  3088 00003DD4 06                  <1> 	push	es ; gs (UDATA)
  3089 00003DD5 66BA1000            <1> 	mov	dx, KDATA
  3090 00003DD9 8EC2                <1> 	mov	es, dx
  3091                              <1> 	;
  3092                              <1> 	;; pushad simulation
  3093 00003DDB 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3094 00003DDD 50                  <1> 	push	eax ; eax (0)
  3095 00003DDE 50                  <1> 	push	eax ; ecx (0)
  3096 00003DDF 50                  <1> 	push	eax ; edx (0)
  3097 00003DE0 50                  <1> 	push	eax ; ebx (0)
  3098 00003DE1 55                  <1> 	push	ebp ; esp before pushad
  3099 00003DE2 50                  <1> 	push	eax ; ebp (0)
  3100 00003DE3 50                  <1> 	push	eax ; esi (0)		
  3101 00003DE4 50                  <1> 	push	eax ; edi (0)	
  3102                              <1> 	;
  3103 00003DE5 A3[EC640000]        <1> 	mov	[u.r0], eax ; eax = 0
  3104 00003DEA 8925[E8640000]      <1> 	mov	[u.usp], esp
  3105                              <1> 		; mov r5,u.r0 /
  3106                              <1> 		; sub $16.,r5 / skip 8 words
  3107                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3108                              <1> 		;             / effectively zeroes all regs
  3109                              <1> 			    ; / when sysrele is executed
  3110                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3111                              <1> 		; clr u.break
  3112                              <1> 		; mov r5,sp / point sp to user's stack
  3113                              <1> 	;
  3114 00003DF0 E9F8F2FFFF          <1> 	jmp	sysret0
  3115                              <1> 	;jmp	sysret
  3116                              <1> 		; br sysret3 / return to core image at $core
  3117                              <1> 
  3118                              <1> get_argp:
  3119                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3120                              <1> 	; 18/10/2015 (nbase, ncount)
  3121                              <1> 	; 21/07/2015
  3122                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3123                              <1> 	; Get (virtual) address of argument from user's core memory
  3124                              <1> 	;
  3125                              <1> 	; INPUT:
  3126                              <1> 	;	esi = virtual address of argument pointer
  3127                              <1> 	; OUTPUT:
  3128                              <1> 	;	eax = virtual address of argument
  3129                              <1> 	;
  3130                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3131                              <1> 	;
  3132 00003DF5 833D[49650000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3133                              <1> 				    ; (the caller is kernel)
  3134                              <1> 	;jna	short get_argpk 
  3135                              <1> 	; 24/12/2021
  3136 00003DFC 7719                <1> 	ja	short get_argp5
  3137                              <1> get_argpk:
  3138                              <1> 	; Argument is in kernel's memory space
  3139 00003DFE 66C705[68650000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3139 00003E06 10                  <1>
  3140 00003E07 8935[64650000]      <1> 	mov	[nbase], esi
  3141 00003E0D 8305[64650000]04    <1> 	add	dword [nbase], 4
  3142 00003E14 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3143 00003E16 C3                  <1> 	retn
  3144                              <1> get_argp5:
  3145 00003E17 89F3                <1>      	mov	ebx, esi
  3146 00003E19 E88BE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3147 00003E1E 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3148 00003E20 A3[64650000]        <1> 	mov 	[nbase], eax ; physical address	
  3149 00003E25 66890D[68650000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3150 00003E2C B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3151                              <1> 	;cmp	cx, ax ; 4
  3152 00003E31 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3153 00003E33 734C                <1> 	jnb	short get_argp2
  3154 00003E35 89F3                <1> 	mov	ebx, esi
  3155 00003E37 01CB                <1> 	add	ebx, ecx
  3156 00003E39 E86BE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3157 00003E3E 7237                <1> 	jc	short get_argp_err
  3158                              <1> 	;push	esi
  3159 00003E40 89C6                <1> 	mov	esi, eax
  3160 00003E42 66870D[68650000]    <1> 	xchg	cx, [ncount]
  3161 00003E49 8735[64650000]      <1> 	xchg	esi, [nbase]
  3162 00003E4F B504                <1> 	mov	ch, 4
  3163 00003E51 28CD                <1> 	sub	ch, cl
  3164                              <1> get_argp0:
  3165 00003E53 AC                  <1> 	lodsb
  3166                              <1> 	;push	ax
  3167                              <1> 	; 24/12/2021
  3168 00003E54 50                  <1> 	push	eax
  3169 00003E55 FEC9                <1> 	dec	cl
  3170 00003E57 75FA                <1>         jnz     short get_argp0
  3171 00003E59 8B35[64650000]      <1> 	mov	esi, [nbase]
  3172                              <1> 	; 21/07/2015
  3173 00003E5F 0FB6C5              <1> 	movzx	eax, ch
  3174 00003E62 0105[64650000]      <1> 	add	[nbase], eax
  3175 00003E68 662905[68650000]    <1> 	sub	[ncount], ax
  3176                              <1> get_argp1:
  3177 00003E6F AC                  <1> 	lodsb
  3178 00003E70 FECD                <1> 	dec	ch
  3179 00003E72 7423                <1>         jz      short get_argp3
  3180                              <1> 	;push	ax
  3181                              <1> 	; 24/12/2021
  3182 00003E74 50                  <1> 	push	eax
  3183 00003E75 EBF8                <1> 	jmp     short get_argp1
  3184                              <1> 	; 24/12/2021
  3185                              <1> get_argp_err:
  3186 00003E77 A3[41650000]        <1> 	mov	[u.error], eax
  3187 00003E7C E94AF2FFFF          <1> 	jmp	error
  3188                              <1> get_argp2:
  3189                              <1> 	; 21/07/2015
  3190                              <1> 	;mov	eax, 4
  3191 00003E81 8B15[64650000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3192 00003E87 0105[64650000]      <1> 	add	[nbase], eax
  3193 00003E8D 662905[68650000]    <1> 	sub	[ncount], ax
  3194                              <1> 	;
  3195 00003E94 8B02                <1> 	mov	eax, [edx]
  3196 00003E96 C3                  <1> 	retn
  3197                              <1> get_argp3:
  3198 00003E97 B103                <1> 	mov	cl, 3
  3199                              <1> get_argp4:
  3200 00003E99 C1E008              <1> 	shl	eax, 8
  3201                              <1> 	;pop	dx
  3202                              <1> 	; 24/12/2021
  3203 00003E9C 5A                  <1> 	pop	edx
  3204 00003E9D 88D0                <1> 	mov 	al, dl
  3205 00003E9F E2F8                <1>         loop    get_argp4
  3206                              <1> 	;pop	esi
  3207 00003EA1 C3                  <1> 	retn	
  3208                              <1> 
  3209                              <1> sysfstat:
  3210                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3211                              <1> 	;	([idev] return in eax)
  3212                              <1> 	;	0 = root device
  3213                              <1> 	;	1 = mounted device (>0)
  3214                              <1> 	; 03/02/2022
  3215                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3216                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3217                              <1> 	;
  3218                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3219                              <1> 	; on open files instead of files given by name. It puts the
  3220                              <1> 	; buffer address on the stack, gets the i-number and
  3221                              <1> 	; checks to see if the file is open for reading or writing.
  3222                              <1> 	; If the file is open for writing (i-number is negative)
  3223                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3224                              <1> 	; is made.	
  3225                              <1> 	;
  3226                              <1> 	; Calling sequence:
  3227                              <1> 	;	sysfstat; buf
  3228                              <1> 	; Arguments:
  3229                              <1> 	;	buf - buffer address
  3230                              <1> 	;
  3231                              <1> 	; Inputs: *u.r0 - file descriptor
  3232                              <1> 	; Outputs: buffer is loaded with file information
  3233                              <1> 	; ...............................................................
  3234                              <1> 	;				
  3235                              <1> 	; Retro UNIX 8086 v1 modification:
  3236                              <1> 	;       'sysfstat' system call has two arguments; so,
  3237                              <1> 	;	* 1st argument, file descriptor is in BX register
  3238                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3239                              <1> 
  3240                              <1> 	; / set status of open file
  3241                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3242 00003EA2 51                  <1> 	push	ecx
  3243                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3244                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3245                              <1> 		; jsr r0,getf / get the files i-number
  3246                              <1> 	; BX = file descriptor (file number)
  3247 00003EA3 E8FE000000          <1> 	call	getf1
  3248                              <1> 	; 03/02/2022
  3249 00003EA8 21C0                <1> 	and	eax, eax
  3250                              <1> 	;and	ax, ax ; i-number of the file
  3251                              <1> 		; tst	r1 / is it 0?
  3252                              <1> 	;jz	error
  3253                              <1> 		; beq error3 / yes, error
  3254 00003EAA 750F                <1> 	jnz	short sysfstat1
  3255 00003EAC C705[41650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3255 00003EB4 0000                <1>
  3256 00003EB6 E910F2FFFF          <1> 	jmp	error
  3257                              <1> sysfstat1:
  3258 00003EBB 80FC80              <1> 	cmp	ah, 80h
  3259 00003EBE 7222                <1>         jb      short sysstat1
  3260                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3261 00003EC0 66F7D8              <1> 	neg	ax
  3262                              <1> 		; neg r1 / make it positive, then branch
  3263 00003EC3 EB1D                <1> 	jmp	short sysstat1
  3264                              <1> 		; br 1f / to 1f
  3265                              <1> sysstat:
  3266                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3267                              <1> 	;	([idev] return in eax)
  3268                              <1> 	;	0 = root device
  3269                              <1> 	;	1 = mounted device (>0)
  3270                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3271                              <1> 	; 18/10/2015
  3272                              <1> 	; 07/10/2015
  3273                              <1> 	; 02/09/2015
  3274                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3275                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3276                              <1> 	;
  3277                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3278                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3279                              <1> 	; long and information about the file placed in it.	
  3280                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3281                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3282                              <1> 	; is then loaded and the results are given in the UNIX
  3283                              <1> 	; Programmers Manual sysstat (II).	
  3284                              <1> 	;
  3285                              <1> 	; Calling sequence:
  3286                              <1> 	;	sysstat; name; buf
  3287                              <1> 	; Arguments:
  3288                              <1> 	;	name - points to the name of the file
  3289                              <1> 	;	buf - address of a 34 bytes buffer
  3290                              <1> 	; Inputs: -
  3291                              <1> 	; Outputs: buffer is loaded with file information
  3292                              <1> 	; ...............................................................
  3293                              <1> 	;				
  3294                              <1> 	; Retro UNIX 8086 v1 modification: 
  3295                              <1> 	;       'sysstat' system call has two arguments; so,
  3296                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3297                              <1> 	;	to get sysstat system call arguments from the user;
  3298                              <1> 	;	* 1st argument, name is pointed to by BX register
  3299                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3300                              <1> 	;
  3301                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3302                              <1> 	;	      arguments which were in these registers;
  3303                              <1> 	;	      but, it returns by putting the 1st argument
  3304                              <1> 	;	      in 'u.namep' and the 2nd argument
  3305                              <1> 	;	      on top of stack. (1st argument is offset of the
  3306                              <1> 	;	      file/path name in the user's program segment.)		 	
  3307                              <1> 	
  3308                              <1> 	; / ; name of file; buffer - get files status
  3309                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3310 00003EC5 891D[04650000]      <1> 	mov	[u.namep], ebx
  3311 00003ECB 51                  <1> 	push	ecx
  3312 00003ECC E806010000          <1> 	call	namei
  3313                              <1> 		; jsr r0,namei / get the i-number for the file
  3314                              <1> 	;jc	error
  3315                              <1> 		; br error3 / no such file, error
  3316 00003ED1 730F                <1> 	jnc	short sysstat1
  3317                              <1> 	; pop 	ecx
  3318                              <1> sysstat_err0:
  3319                              <1> 	; 'file not found !' error
  3320 00003ED3 C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3320 00003EDB 0000                <1>
  3321 00003EDD E9E9F1FFFF          <1> 	jmp	error
  3322                              <1> 
  3323                              <1> ;statx: db 0
  3324                              <1> 
  3325                              <1> sysstat1: ; 1:
  3326 00003EE2 E800090000          <1> 	call	iget
  3327                              <1> 		; jsr r0,iget / get the i-node into core
  3328                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3329                              <1> 	; 02/09/2015
  3330 00003EE7 8F05[0C650000]      <1> 	pop	dword [u.base]
  3331                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3332 00003EED E861000000          <1> 	call	sysstat_gpa ; get physical address
  3333 00003EF2 730A                <1> 	jnc 	short sysstat2
  3334                              <1> sysstat_err1:
  3335 00003EF4 A3[41650000]        <1> 	mov	dword [u.error], eax ; error code
  3336 00003EF9 E9CDF1FFFF          <1> 	jmp	error
  3337                              <1> sysstat2:
  3338 00003EFE A0[D0640000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3339 00003F03 AA                  <1> 	stosb
  3340 00003F04 FF05[0C650000]      <1> 	inc 	dword [u.base]
  3341                              <1> 	;dec 	cx
  3342                              <1> 	; 24/12/2021
  3343 00003F0A 49                  <1> 	dec	ecx
  3344 00003F0B 7505                <1> 	jnz	short sysstat3
  3345 00003F0D E841000000          <1> 	call	sysstat_gpa
  3346                              <1> 	;jc	short sysstat_err1
  3347                              <1> sysstat3:
  3348 00003F12 A0[D1640000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3349 00003F17 AA                  <1> 	stosb
  3350                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3351 00003F18 FF05[0C650000]      <1> 	inc 	dword [u.base]
  3352                              <1> 	;;dec 	word [u.pcount]
  3353                              <1> 	;dec	cx
  3354 00003F1E 49                  <1> 	dec	ecx ; 24/12/2021
  3355 00003F1F 7505                <1> 	jnz	short sysstat4
  3356 00003F21 E82D000000          <1> 	call	sysstat_gpa
  3357                              <1> 	;jc	short sysstat_err1	
  3358                              <1> sysstat4:
  3359 00003F26 BE[E4610000]        <1> 	mov	esi, inode
  3360                              <1> 		; mov $inode,r2 / r2 points to i-node
  3361                              <1> sysstat5: ; 1:
  3362 00003F2B A4                  <1> 	movsb
  3363                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3364 00003F2C FF05[0C650000]      <1> 	inc 	dword [u.base]
  3365                              <1> 	;;dec 	word [u.pcount]
  3366                              <1> 	;dec 	cx
  3367                              <1> 	; 24/12/2021
  3368 00003F32 49                  <1> 	dec	ecx
  3369 00003F33 7505                <1> 	jnz	short sysstat6
  3370 00003F35 E819000000          <1> 	call	sysstat_gpa
  3371                              <1> 	;jc	short sysstat_err1
  3372                              <1> sysstat6:		
  3373 00003F3A 81FE[04620000]      <1> 	cmp	esi, inode + 32
  3374                              <1> 		; cmp r2,$inode+32 / done?
  3375 00003F40 75E9                <1> 	jne	short sysstat5
  3376                              <1> 		; bne 1b / no, go back
  3377                              <1> 
  3378                              <1> 	;;;
  3379                              <1> 	; 09/05/2022
  3380                              <1> 	;*** additional feature *** -retro unix only- 
  3381                              <1> 	;
  3382                              <1> 	; !! return device number -of current inode- in eax !!
  3383                              <1> 	;
  3384                              <1> 	; (modification reason/purpose:
  3385                              <1> 	; to improve 'pwd' command's pathname output/result
  3386                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3387                              <1> 	; error due to same inode numbers in root file system
  3388                              <1> 	; and mounted file system.)
  3389                              <1> 	;
  3390 00003F42 29C0                <1> 	sub	eax, eax
  3391 00003F44 A0[D2640000]        <1> 	mov	al, [idev] ; [cdev]
  3392 00003F49 A3[EC640000]        <1> 	mov	[u.r0], eax
  3393                              <1> 	;;;  
  3394                              <1> 
  3395 00003F4E E998F1FFFF          <1> 	jmp	sysret
  3396                              <1> 		; br sysret3 / return through sysret
  3397                              <1> 	;
  3398                              <1> sysstat_gpa: ; get physical address of file status buffer
  3399                              <1> 	; 02/09/2015
  3400 00003F53 8B1D[0C650000]      <1> 	mov 	ebx, [u.base]
  3401                              <1> 	; 07/10/2015
  3402 00003F59 E84BE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3403                              <1> 	;jc	short sysstat_gpa1
  3404 00003F5E 7294                <1> 	jc	short sysstat_err1
  3405                              <1> 	; 18/10/2015
  3406 00003F60 89C7                <1> 	mov	edi, eax ; physical address
  3407                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3408                              <1> ;sysstat_gpa1:
  3409 00003F62 C3                  <1> 	retn
  3410                              <1> 
  3411                              <1> fclose:
  3412                              <1> 	; 08/01/2022
  3413                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3414                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3415                              <1> 	;            (32 bit offset pointer modification)
  3416                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3417                              <1> 	;
  3418                              <1> 	; Given the file descriptor (index to the u.fp list)
  3419                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3420                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3421                              <1> 	; u.fp list is cleared. If all the processes that opened
  3422                              <1> 	; that file close it, then fsp etry is freed and the file
  3423                              <1> 	; is closed. If not a return is taken. 
  3424                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3425                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3426                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3427                              <1> 	; a check is made to see if the file is special.	
  3428                              <1> 	;
  3429                              <1> 	; INPUTS ->
  3430                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3431                              <1> 	;    u.fp - list of entries in the fsp table
  3432                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3433                              <1> 	; OUTPUTS ->
  3434                              <1> 	;    r1 - contains the same file descriptor
  3435                              <1> 	;    r2 - contains i-number
  3436                              <1> 	;
  3437                              <1> 	; ((AX = R1))
  3438                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3439                              <1> 	;
  3440                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3441                              <1> 	;              if i-number of the file is 0. (error)  	
  3442                              <1> 
  3443                              <1> 	;movzx	edx, ax ; **
  3444                              <1> 	; 24/12/2021
  3445                              <1> 	;movzx	edx, al
  3446 00003F63 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3447 00003F65 50                  <1> 	push	eax ; ***
  3448                              <1> 	;push	ax ; ***
  3449                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3450                              <1> 			     ; / the index to u.fp list)
  3451 00003F66 E839000000          <1> 	call	getf
  3452                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3453                              <1> 			    ; / cdev has device =, u.fofp 
  3454                              <1> 			    ; / points to 3rd word of fsp entry
  3455 00003F6B 6683F801            <1> 	cmp	ax, 1 ; r1
  3456                              <1> 		; tst r1 / is i-number 0?
  3457 00003F6F 7231                <1> 	jb	short fclose_2
  3458                              <1> 		; beq 1f / yes, i-node not active so return
  3459                              <1> 		; tst (r0)+ / no, jump over error return
  3460 00003F71 89D3                <1> 	mov	ebx, edx ; **
  3461                              <1> 	; 24/12/2021
  3462 00003F73 89C2                <1> 	mov	edx, eax ; *
  3463                              <1> 	;mov 	dx, ax ; *
  3464                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3465                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3466                              <1> 			    ; / which is index to u.fp ; **
  3467 00003F75 C683[F2640000]00    <1> 	mov	byte [ebx+u.fp], 0
  3468                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3469 00003F7C 8B1D[FC640000]      <1> 	mov	ebx, [u.fofp]
  3470                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3471                              <1> fclose_0:
  3472 00003F82 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3473                              <1> 		; decb 2(r1) / decrement the number of processes 
  3474                              <1> 			   ; / that have opened the file
  3475 00003F85 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3476                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3477                              <1> 	;
  3478                              <1> 	; 24/12/2021
  3479 00003F87 52                  <1> 	push	edx ; *
  3480                              <1> 	;push	dx ; *
  3481                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3482                              <1> 	;xor	ax, ax ; 0
  3483                              <1> 	; 24/12/2021
  3484 00003F88 31C0                <1> 	xor	eax, eax
  3485 00003F8A 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3486                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3487 00003F8E 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3488                              <1> 		; tstb	3(r1) / has this file been deleted
  3489 00003F91 20C0                <1> 	and	al, al
  3490 00003F93 7407                <1> 	jz	short fclose_1
  3491                              <1> 		; beq 2f / no, branch
  3492                              <1> 	; 08/01/2022
  3493 00003F95 89D0                <1> 	mov	eax, edx
  3494                              <1> 	;mov	ax, dx ; *
  3495                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3496                              <1> 	; AX = inode number
  3497 00003F97 E8A0040000          <1> 	call	anyi
  3498                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3499                              <1> 			    ; / check if file appears in fsp again
  3500                              <1> fclose_1: ; 2:
  3501                              <1> 	; 24/12/2021
  3502 00003F9C 58                  <1> 	pop	eax ; * 
  3503                              <1> 	;pop	ax ; *
  3504                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3505 00003F9D E8E8110000          <1> 	call	iclose ; close if it is special file 
  3506                              <1> 		; jsr r0,iclose / check to see if its a special file
  3507                              <1> fclose_2: ; 1:
  3508                              <1> 	; 24/12/2021
  3509 00003FA2 58                  <1> 	pop	eax ; ***
  3510                              <1> 	;pop	ax ; ***
  3511                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3512 00003FA3 C3                  <1> 	retn
  3513                              <1> 		; rts r0
  3514                              <1> 
  3515                              <1> 	; 09/01/2022
  3516                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3517                              <1> getf:	; / get the device number and the i-number of an open file
  3518                              <1> 	; 13/05/2015
  3519                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3520                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3521                              <1> 	;
  3522 00003FA4 89C3                <1> 	mov	ebx, eax
  3523                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3524                              <1> 	; 08/01/2022
  3525 00003FA6 29C0                <1> 	sub	eax, eax
  3526                              <1> 	;
  3527 00003FA8 83FB0A              <1> 	cmp	ebx, 10
  3528                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3529 00003FAB 7329                <1>         jnb	short getf2 ; 13/05/2015
  3530                              <1> 	;jnb	error
  3531                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3532                              <1> 			    ; / index in fsp table
  3533                              <1> 	; 08/01/2022
  3534 00003FAD 8A83[F2640000]      <1> 	mov	al, [ebx+u.fp]
  3535                              <1> 	;mov	bl, [ebx+u.fp]
  3536                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3537                              <1> 		                  ; / in fsp table
  3538                              <1> 	; 08/01/2022
  3539 00003FB3 08C0                <1> 	or	al, al
  3540 00003FB5 741F                <1> 	jz	short getf2	
  3541                              <1> 	;or	bl, bl
  3542                              <1> 	;jnz	short getf3
  3543                              <1> 	;;jz	short getf4
  3544                              <1> 		; beq 1f / if its zero return
  3545                              <1> ;getf2:
  3546                              <1> ;	; 08/01/2022
  3547                              <1> ;	; 'File not open !' error (ax=0)
  3548                              <1> ;	;sub	eax, eax
  3549                              <1> ;	retn
  3550                              <1> 
  3551                              <1> getf3:	
  3552                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3553                              <1> 	;
  3554                              <1> 	; 'fsp' table (10 bytes/entry)
  3555                              <1> 	; bit 15				   bit 0
  3556                              <1> 	; ---|-------------------------------------------
  3557                              <1> 	; r/w|		i-number of open file
  3558                              <1> 	; ---|-------------------------------------------
  3559                              <1> 	;		   device number
  3560                              <1> 	; -----------------------------------------------
  3561                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3562                              <1> 	; -----------------------------------------------
  3563                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3564                              <1> 	; ----------------------|------------------------
  3565                              <1> 	;  flag that says file 	| number of processes
  3566                              <1> 	;   has been deleted	| that have file open 
  3567                              <1> 	; ----------------------|------------------------
  3568                              <1> 	;
  3569                              <1> 	;mov	eax, 10
  3570                              <1> 	; 08/01/2022
  3571 00003FB7 B30A                <1> 	mov	bl, 10
  3572 00003FB9 F6E3                <1> 	mul	bl
  3573 00003FBB BB[AE620000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3574 00003FC0 01C3                <1> 	add	ebx, eax
  3575                              <1> 		; asl r1
  3576                              <1> 		; asl r1 / multiply by 8 to get index into 
  3577                              <1> 		       ; / fsp table entry
  3578                              <1> 		; asl r1
  3579                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3580                              <1> 			      ; / in the fsp entry
  3581 00003FC2 891D[FC640000]      <1> 	mov	[u.fofp], ebx
  3582                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3583                              <1> 			      ; / in fsp entry in u.fofp
  3584 00003FC8 4B                  <1> 	dec	ebx
  3585 00003FC9 4B                  <1> 	dec	ebx
  3586                              <1> 	;mov	ax, [ebx]
  3587                              <1> 	; 09/01/2022
  3588 00003FCA 8A03                <1> 	mov	al, [ebx]
  3589 00003FCC A2[D3640000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3590                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3591                              <1> 			     ;;dev number is in 1 byte
  3592                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3593 00003FD1 4B                  <1> 	dec	ebx
  3594 00003FD2 4B                  <1> 	dec	ebx
  3595 00003FD3 668B03              <1> 	mov	ax, [ebx]
  3596                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3597                              <1> getf2:	; 08/01/2022
  3598                              <1> getf4:	; 1:
  3599 00003FD6 C3                  <1> 	retn
  3600                              <1> 		; rts r0
  3601                              <1> 
  3602                              <1> namei:
  3603                              <1> 	; 15/05/2022 (mounted directory path, '..' method)
  3604                              <1> 	; 03/02/2022
  3605                              <1> 	; 09/01/2022
  3606                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3607                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3608                              <1> 	; 18/10/2015 (nbase, ncount)
  3609                              <1> 	; 12/10/2015
  3610                              <1> 	; 21/08/2015
  3611                              <1> 	; 18/07/2015
  3612                              <1> 	; 02/07/2015
  3613                              <1> 	; 17/06/2015
  3614                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3615                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3616                              <1> 	;
  3617                              <1> 	; 'namei' takes a file path name and returns i-number of
  3618                              <1> 	; the file in the current directory or the root directory
  3619                              <1> 	; (if the first character of the pathname is '/').	
  3620                              <1> 	;
  3621                              <1> 	; INPUTS ->
  3622                              <1> 	;    u.namep - points to a file path name
  3623                              <1> 	;    u.cdir - i-number of users directory
  3624                              <1> 	;    u.cdev - device number on which user directory resides	
  3625                              <1> 	; OUTPUTS ->
  3626                              <1> 	;    r1 - i-number of file
  3627                              <1> 	;    cdev
  3628                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3629                              <1> 	;               occurs in the search for file path name.
  3630                              <1> 	;	        If no match u.dirb points to the end of 
  3631                              <1> 	;               the directory and r1 = i-number of the current
  3632                              <1> 	;	        directory.	
  3633                              <1> 	; ((AX = R1))
  3634                              <1> 	;
  3635                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3636                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3637                              <1> 	;
  3638                              <1> 
  3639 00003FD7 66A1[F0640000]      <1> 	mov	ax, [u.cdir]
  3640                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3641                              <1> 			      ; / in r1
  3642                              <1> 	; 09/01/2022
  3643 00003FDD 8A15[36650000]      <1> 	mov	dl, [u.cdrv]
  3644 00003FE3 8815[D3640000]      <1> 	mov	[cdev], dl
  3645                              <1> 	;mov	dx, [u.cdrv]
  3646                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3647                              <1> 				    ; device/drive number is in 1 byte, 
  3648                              <1> 				    ; not in 1 word!
  3649                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3650                              <1> 				; / into cdev
  3651                              <1> 	; 12/10/2015
  3652                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3653                              <1>       	 ; convert virtual (pathname) addr to physical address
  3654 00003FE9 E868010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3655                              <1> 		; esi = physical address of [u.namep]
  3656                              <1> 		; ecx = byte count in the page
  3657 00003FEE 803E2F              <1> 	cmp	byte [esi], '/'
  3658                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3659 00003FF1 751D                <1> 	jne	short namei_1
  3660                              <1> 		; bne 1f
  3661 00003FF3 FF05[04650000]      <1> 	inc	dword [u.namep]
  3662                              <1> 		; inc u.namep / go to next char
  3663                              <1> 	;dec	cx ; remain byte count in the page
  3664                              <1> 	; 24/12/2021
  3665 00003FF9 49                  <1> 	dec	ecx
  3666 00003FFA 7506                <1> 	jnz	short namei_0
  3667                              <1> 	; 12/10/2015
  3668 00003FFC E855010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3669                              <1> 		; esi = physical address (page start + offset)
  3670                              <1> 		; ecx = byte count in the page
  3671 00004001 4E                  <1> 	dec	esi
  3672                              <1> namei_0:
  3673 00004002 46                  <1> 	inc 	esi  ; go to next char
  3674 00004003 66A1[DC640000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3675                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3676 00004009 C605[D3640000]00    <1> 	mov	byte [cdev], 0
  3677                              <1> 		; clr cdev / clear device number
  3678                              <1> namei_1: ; 1:
  3679 00004010 F606FF              <1> 	test	byte [esi], 0FFh
  3680                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3681 00004013 74C1                <1> 	jz	short getf4
  3682                              <1> 	;jz	nig
  3683                              <1> 		; tstb *u.namep / is the character in file name a nul
  3684                              <1> 		; beq nig / yes, end of file name reached; 
  3685                              <1> 			; / branch to "nig"
  3686                              <1> namei_2: ; 1:
  3687                              <1> 	; 18/10/2015
  3688 00004015 8935[64650000]      <1> 	mov 	[nbase], esi
  3689 0000401B 66890D[68650000]    <1> 	mov 	[ncount], cx
  3690                              <1> 	;
  3691                              <1> 	;mov	dx, 2
  3692 00004022 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3693 00004024 E892080000          <1> 	call	access
  3694                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3695                              <1> 	; 'access' will not return here if user has not "r" permission !
  3696                              <1> 	; 03/02/2022
  3697 00004029 F605[E5610000]40    <1> 	test	byte [i.flgs+1], 40h
  3698                              <1> 	;test 	word [i.flgs], 4000h
  3699                              <1> 		; bit $40000,i.flgs / directory i-node?
  3700 00004030 746A                <1>         jz      short namei_err
  3701                              <1> 		; beq error3 / no, got an error
  3702                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3703 00004032 31C0                <1> 	xor	eax, eax
  3704 00004034 A3[08650000]        <1> 	mov	[u.off], eax ; 0
  3705 00004039 66A1[E8610000]      <1> 	mov	ax, [i.size]
  3706 0000403F A3[00650000]        <1> 	mov	[u.dirp], eax
  3707                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3708                              <1> 		; clr u.off / u.off is file offset used by user
  3709 00004044 C705[FC640000]-     <1> 	mov	dword [u.fofp], u.off
  3709 0000404A [08650000]          <1>
  3710                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3711                              <1> 				  ; / the offset portion of fsp entry
  3712                              <1> namei_3: ; 2:
  3713 0000404E C705[0C650000]-     <1> 	mov	dword [u.base], u.dirbuf
  3713 00004054 [1E650000]          <1>
  3714                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3715                              <1> 				    ; / copied from a directory
  3716 00004058 C705[10650000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3716 00004060 0000                <1>
  3717                              <1>  		; mov $10.,u.count / u.count is byte count 
  3718                              <1> 				 ; / for reads and writes
  3719 00004062 66A1[D0640000]      <1> 	mov 	ax, [ii]
  3720                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3721 00004068 FE05[53650000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3722 0000406E E848090000          <1>     	call	readi
  3723                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3724                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3725 00004073 8B0D[14650000]      <1> 	mov 	ecx, [u.nread]
  3726 00004079 09C9                <1> 	or 	ecx, ecx
  3727                              <1> 		; tst u.nread
  3728 0000407B 741B                <1> 	jz	short nib
  3729                              <1> 		; ble nib / gives error return
  3730                              <1> 	;
  3731 0000407D 668B1D[1E650000]    <1> 	mov 	bx, [u.dirbuf]
  3732 00004084 6621DB              <1> 	and 	bx, bx       
  3733                              <1> 		; tst u.dirbuf /
  3734 00004087 7522                <1> 	jnz	short namei_4
  3735                              <1> 		; bne 3f / branch when active directory entry 
  3736                              <1> 		       ; / (i-node word in entry non zero)
  3737 00004089 A1[08650000]        <1> 	mov	eax, [u.off]
  3738 0000408E 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3739 00004091 A3[00650000]        <1> 	mov	[u.dirp], eax
  3740                              <1> 		; mov u.off,u.dirp
  3741                              <1> 		; sub $10.,u.dirp
  3742 00004096 EBB6                <1> 	jmp	short namei_3
  3743                              <1> 		; br 2b
  3744                              <1> 
  3745                              <1> 	; 18/07/2013
  3746                              <1> nib: 
  3747 00004098 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3748 0000409A F9                  <1> 	stc
  3749                              <1> nig:
  3750 0000409B C3                  <1> 	retn
  3751                              <1> 
  3752                              <1> namei_err:
  3753                              <1> 	; 16/06/2015
  3754 0000409C C705[41650000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3754 000040A4 0000                <1>
  3755 000040A6 E920F0FFFF          <1> 	jmp	error
  3756                              <1> 
  3757                              <1> namei_4: ; 3:
  3758                              <1> 	; 18/10/2015
  3759                              <1> 	; 12/10/2015
  3760                              <1> 	; 21/08/2015
  3761                              <1> 	; 18/07/2015
  3762 000040AB 8B2D[04650000]      <1> 	mov	ebp, [u.namep]
  3763                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3764 000040B1 BF[20650000]        <1> 	mov 	edi, u.dirbuf + 2
  3765                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3766                              <1> 	; 18/10/2015
  3767 000040B6 8B35[64650000]      <1> 	mov	esi, [nbase]	
  3768 000040BC 668B0D[68650000]    <1> 	mov	cx, [ncount]
  3769                              <1> 	;
  3770 000040C3 6621C9              <1> 	and	cx, cx
  3771 000040C6 7505                <1> 	jnz	short namei_5	
  3772                              <1> 	;
  3773 000040C8 E88F000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3774                              <1> 		; esi = physical address (page start + offset)
  3775                              <1> 		; ecx = byte count in the page
  3776                              <1> namei_5: ; 3:
  3777 000040CD 45                  <1> 	inc	ebp ; 18/07/2015
  3778 000040CE AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3779                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3780 000040CF 08C0                <1> 	or 	al, al
  3781 000040D1 741C                <1> 	jz 	short namei_7
  3782                              <1> 		; beq 3f / if char is nul, then the last char in string
  3783                              <1> 			; / has been moved
  3784 000040D3 3C2F                <1> 	cmp	al, '/'
  3785                              <1> 		; cmp r4,$'/ / is char a </>
  3786 000040D5 7418                <1> 	je 	short namei_7
  3787                              <1> 		; beq 3f	
  3788                              <1> 	; 24/12/2021
  3789 000040D7 49                  <1> 	dec	ecx
  3790                              <1> 	; 12/10/2015
  3791                              <1> 	;dec	cx ; remain byte count in the page
  3792 000040D8 7505                <1> 	jnz	short namei_6
  3793 000040DA E87D000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3794                              <1> 		; esi = physical address (page start + offset)
  3795                              <1> 		; ecx = byte count in the page
  3796                              <1> namei_6:
  3797 000040DF 81FF[2E650000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3798                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3799                              <1> 				     ; / all 8 bytes of file name
  3800 000040E5 74E6                <1> 	je	short namei_5
  3801                              <1> 		; beq 3b
  3802 000040E7 AE                  <1> 	scasb	
  3803                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3804                              <1> 			      ; / char read from directory
  3805 000040E8 74E3                <1> 	je 	short namei_5
  3806                              <1> 		; beq 3b / branch if chars match
  3807                              <1> namei_9:
  3808 000040EA E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3809                              <1> 		; br 2b / file names do not match go to next directory entry
  3810                              <1> namei_7: ; 3:
  3811 000040EF 81FF[2E650000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3812                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3813 000040F5 7406                <1> 	je	short namei_8
  3814                              <1> 		; beq 3f
  3815 000040F7 8A27                <1> 	mov 	ah, [edi]
  3816                              <1> 	;inc 	edi 
  3817 000040F9 20E4                <1> 	and 	ah, ah
  3818                              <1> 		; tstb (r3)+ /
  3819                              <1>         ;jnz	namei_3
  3820                              <1> 		; bne 2b
  3821                              <1> 	; 24/12/2021
  3822 000040FB 75ED                <1> 	jnz	short namei_9	
  3823                              <1> namei_8: ; 3
  3824 000040FD 892D[04650000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3825                              <1> 		; mov r2,u.namep / u.namep points to char 
  3826                              <1> 			       ; / following a / or nul
  3827                              <1> 	;mov	bx, [u.dirbuf]
  3828                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3829                              <1> 				; / entry to r1
  3830                              <1> 	;;;;
  3831                              <1> 	; 15/05/2022 - Retro UNIX (8086/386) feature only !
  3832                              <1> 	; ! 'pwd' utility modification !
  3833                              <1> 	; ((if directory entry name is a dotdot)))
  3834                              <1> 	;; check if it is mounted device's root directory inode
  3835                              <1> 	; and if so, replace it with parent dir inode number
  3836                              <1> 	;  of mounting directory in [mntp].
  3837                              <1> 
  3838 00004103 668B1D[1E650000]    <1> 	mov	bx, [u.dirbuf]
  3839                              <1> 
  3840 0000410A 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3841 0000410E 753C                <1> 	jne	short namei_11
  3842                              <1> 
  3843 00004110 663B1D[D0640000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3844 00004117 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3845                              <1> 
  3846                              <1> 	;cmp	[idev], bh ; 0
  3847 00004119 383D[D3640000]      <1> 	cmp	[cdev], bh ; 0
  3848                              <1> 			; 0 = root fs, dev num in [rdev]
  3849                              <1> 			; 1 = mounted, dev num in [mdev]
  3850 0000411F 762B                <1> 	jna	short namei_11
  3851                              <1> 
  3852                              <1> 	; dotdot (parent directory link) check
  3853 00004121 66813D[20650000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3853 00004129 2E                  <1>
  3854 0000412A 7520                <1> 	jne	short namei_11
  3855 0000412C 803D[22650000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3856 00004133 7517                <1> 	jne	short namei_11
  3857                              <1> 	
  3858                              <1> 	; (This may not be necessary because [idev] = 1
  3859                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3860 00004135 66391D[D6640000]    <1> 	cmp	[mnti], bx ; 41
  3861 0000413C 760E                <1> 	jna	short namei_11
  3862                              <1> 	
  3863                              <1> 	; change inumber to parent dir inum of mount directory
  3864 0000413E 668B1D[D8640000]    <1> 	mov	bx, [mntp]
  3865 00004145 C605[D3640000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3866                              <1> namei_11:
  3867                              <1> 	;;;;
  3868                              <1> 
  3869 0000414C 20C0                <1> 	and 	al, al
  3870                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3871                              <1> 		      ;  / if r4 = </> then go to next directory
  3872                              <1> 	; 15/05/2022
  3873 0000414E 6689D8              <1> 	mov	ax, bx
  3874                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3875                              <1>   	; 24/12/2021
  3876 00004151 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3877                              <1> 	;jnz	namei_2 
  3878                              <1> 		; bne 1b
  3879                              <1> 	; AX = i-number of the file
  3880                              <1> ;;nig:
  3881                              <1> 	;retn	; 24/12/2021
  3882                              <1> 		; tst (r0)+ / gives non-error return
  3883                              <1> ;;nib:
  3884                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3885                              <1> 		       ; ax = 0 -> file not found 
  3886                              <1> ;;	stc	; 27/05/2013
  3887                              <1> ;;	retn
  3888                              <1> 		; rts r0
  3889                              <1> 
  3890                              <1> trans_addr_nmbp:
  3891                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3892                              <1> 	; 18/10/2015
  3893                              <1> 	; 12/10/2015
  3894 00004156 8B2D[04650000]      <1> 	mov 	ebp, [u.namep]
  3895                              <1> trans_addr_nm:
  3896                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3897                              <1> 	; Convert virtual (pathname) address to physical address
  3898                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3899                              <1> 	; 18/10/2015
  3900                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3901                              <1> 	; 02/07/2015
  3902                              <1> 	; 17/06/2015
  3903                              <1> 	; 16/06/2015
  3904                              <1> 	;
  3905                              <1> 	; INPUTS: 
  3906                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3907                              <1> 	;	[u.pgdir] = user's page directory
  3908                              <1> 	; OUTPUT:
  3909                              <1> 	;       esi = physical address of the pathname
  3910                              <1> 	;	ecx = remain byte count in the page
  3911                              <1> 	;
  3912                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3913                              <1> 	;
  3914                              <1> 
  3915                              <1> 	; 08/01/2022
  3916 0000415C 29C9                <1> 	sub	ecx, ecx
  3917                              <1> 	;
  3918 0000415E 833D[49650000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3919 00004165 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3920                              <1> 				     ; it is already physical address
  3921 00004167 50                  <1>    	push	eax	
  3922 00004168 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3923 0000416A E83AE6FFFF          <1>        	call	get_physical_addr ; get physical address
  3924 0000416F 7204                <1> 	jc	short tr_addr_nm_err
  3925                              <1> 	; 18/10/2015
  3926                              <1> 	; eax = physical address 
  3927                              <1> 	; cx = remain byte count in page (1-4096) 
  3928                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3929 00004171 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3930 00004173 58                  <1> 	pop	eax 
  3931 00004174 C3                  <1> 	retn
  3932                              <1> 
  3933                              <1> tr_addr_nm_err:
  3934 00004175 A3[41650000]        <1> 	mov	[u.error], eax
  3935                              <1> 	;pop 	eax
  3936 0000417A E94CEFFFFF          <1> 	jmp	error
  3937                              <1> 
  3938                              <1> trans_addr_nmk:
  3939                              <1> 	; 12/10/2015
  3940                              <1> 	; 02/07/2015
  3941 0000417F 8B35[04650000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3942                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3943                              <1> 	; 08/01/2022
  3944 00004185 B510                <1> 	mov	ch, PAGE_SIZE/256
  3945 00004187 C3                  <1> 	retn
  3946                              <1> 
  3947                              <1> syschdir:
  3948                              <1> 	; / makes the directory specified in the argument
  3949                              <1> 	; / the current directory
  3950                              <1> 	;
  3951                              <1> 	; 09/01/2022
  3952                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3953                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3954                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3955                              <1> 	;
  3956                              <1> 	; 'syschdir' makes the directory specified in its argument
  3957                              <1> 	; the current working directory.
  3958                              <1> 	;
  3959                              <1> 	; Calling sequence:
  3960                              <1> 	;	syschdir; name
  3961                              <1> 	; Arguments:
  3962                              <1> 	;	name - address of the path name of a directory
  3963                              <1> 	;	       terminated by nul byte.	
  3964                              <1> 	; Inputs: -
  3965                              <1> 	; Outputs: -
  3966                              <1> 	; ...............................................................
  3967                              <1> 	;				
  3968                              <1> 	; Retro UNIX 8086 v1 modification:
  3969                              <1> 	;	 The user/application program puts address of 
  3970                              <1> 	;	 the path name in BX register as 'syschdir' 
  3971                              <1> 	; 	 system call argument.
  3972                              <1> 
  3973 00004188 891D[04650000]      <1> 	mov	[u.namep], ebx
  3974                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3975 0000418E E844FEFFFF          <1> 	call	namei
  3976                              <1> 		; jsr r0,namei / find its i-number
  3977                              <1> 	;jc	error
  3978                              <1> 		; br error3
  3979 00004193 730F                <1> 	jnc	short syschdir0
  3980                              <1> 	; 'directory not found !' error
  3981 00004195 C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3981 0000419D 0000                <1>
  3982 0000419F E927EFFFFF          <1> 	jmp	error
  3983                              <1> syschdir0:
  3984                              <1> 	; 08/01/2022
  3985 000041A4 B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3986 000041A6 E810070000          <1> 	call	access
  3987                              <1> 		; jsr r0,access; 2 / get i-node into core
  3988                              <1> 	; 08/01/2022
  3989 000041AB F605[E5610000]40    <1> 	test	byte [i.flgs+1], 40h
  3990                              <1> 	;test	word [i.flgs], 4000h
  3991                              <1> 		; bit $40000,i.flgs / is it a directory?
  3992                              <1> 	;jz	error 
  3993                              <1> 		; beq error3 / no error
  3994 000041B2 750F                <1> 	jnz	short syschdir1
  3995 000041B4 C705[41650000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3995 000041BC 0000                <1>
  3996 000041BE E908EFFFFF          <1> 	jmp	error
  3997                              <1> syschdir1:
  3998 000041C3 66A3[F0640000]      <1> 	mov	[u.cdir], ax
  3999                              <1> 		; mov r1,u.cdir / move i-number to users 
  4000                              <1> 			      ; / current directory
  4001                              <1> 	; 09/01/2022
  4002 000041C9 A0[D3640000]        <1> 	mov	al, [cdev]
  4003 000041CE A2[36650000]        <1> 	mov	[u.cdrv], al
  4004                              <1> 	;mov	ax, [cdev]
  4005                              <1> 	;mov	[u.cdrv], ax
  4006                              <1> 		; mov cdev,u.cdev / move its device to users 
  4007                              <1> 			        ; / current device
  4008 000041D3 E913EFFFFF          <1> 	jmp	sysret
  4009                              <1> 		; br sysret3
  4010                              <1> 
  4011                              <1> syschmod: ; < change mode of file >
  4012                              <1> 	; 29/04/2022 (bugfix)
  4013                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4014                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4015                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4016                              <1> 	;
  4017                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4018                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4019                              <1> 	; changed to 'mode'.
  4020                              <1> 	;
  4021                              <1> 	; Calling sequence:
  4022                              <1> 	;	syschmod; name; mode
  4023                              <1> 	; Arguments:
  4024                              <1> 	;	name - address of the file name
  4025                              <1> 	;	       terminated by null byte.
  4026                              <1> 	;	mode - (new) mode/flags < attributes >
  4027                              <1> 	;	
  4028                              <1> 	; Inputs: -
  4029                              <1> 	; Outputs: -
  4030                              <1> 	; ...............................................................
  4031                              <1> 	;				
  4032                              <1> 	; Retro UNIX 8086 v1 modification: 
  4033                              <1> 	;       'syschmod' system call has two arguments; so,
  4034                              <1> 	;	* 1st argument, name is pointed to by BX register
  4035                              <1> 	;	* 2nd argument, mode is in CX register
  4036                              <1> 	;
  4037                              <1> 	; Mode bits (Flags):
  4038                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4039                              <1> 	;	bit 14 - directory flag (4000h)
  4040                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4041                              <1> 	;	bit 12 - large file flag (1000h)
  4042                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4043                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4044                              <1> 	;	bit 4 - executable flag (10h)
  4045                              <1> 	;	bit 3 - read permission for owner (08h)
  4046                              <1> 	;	bit 2 - write permission for owner (04h)
  4047                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4048                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4049                              <1> 
  4050                              <1> 	; / name; mode
  4051 000041D8 E815000000          <1> 	call	isown
  4052                              <1> 		;jsr r0,isown / get the i-node and check user status
  4053                              <1> 	; 09/01/2022
  4054 000041DD F605[E5610000]40    <1> 	test	byte [i.flgs+1], 40h
  4055                              <1> 	;test	word [i.flgs], 4000h
  4056                              <1> 		; bit $40000,i.flgs / directory?
  4057 000041E4 7402                <1> 	jz	short syschmod1
  4058                              <1> 		; beq 2f / no
  4059                              <1> 	; AL = (new) mode
  4060 000041E6 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4061                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  4062                              <1> 			   ; / executable modes
  4063                              <1> syschmod1: ; 2:
  4064 000041E8 A2[E4610000]        <1> 	mov	[i.flgs], al	
  4065                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  4066                              <1> 	;jmp	short isown1
  4067                              <1> 	;	; br 1f ; (jmp sysret4)
  4068                              <1> 	; 29/04/2022
  4069 000041ED E9F9EEFFFF          <1> 	jmp	sysret
  4070                              <1> 
  4071                              <1> isown:
  4072                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4073                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4074                              <1> 	;
  4075                              <1> 	; 'isown' is given a file name (the 1st argument).
  4076                              <1> 	;  It find the i-number of that file via 'namei' 
  4077                              <1> 	;  then gets the i-node into core via 'iget'.
  4078                              <1> 	;  It then tests to see if the user is super user. 
  4079                              <1> 	;  If not, it cheks to see if the user is owner of 
  4080                              <1> 	;  the file. If he is not an error occurs.
  4081                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4082                              <1> 	;  the inode has been modified and the 2nd argument of
  4083                              <1> 	;  the call is put in r2.
  4084                              <1> 	;
  4085                              <1> 	; INPUTS ->
  4086                              <1> 	;    arguments of syschmod and syschown calls
  4087                              <1> 	; OUTPUTS ->
  4088                              <1> 	;    u.uid - id of user
  4089                              <1> 	;    imod - set to a 1
  4090                              <1> 	;    r2 - contains second argument of the system call				 	
  4091                              <1> 	;
  4092                              <1> 	;   ((AX=R2) output as 2nd argument)
  4093                              <1> 	;
  4094                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4095                              <1> 	;
  4096                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4097                              <1> 	;; ! 2nd argument on top of stack !
  4098                              <1> 	;; 22/06/2015 - 32 bit modifications
  4099                              <1> 	;; 07/07/2013
  4100 000041F2 891D[04650000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4101 000041F8 51                  <1> 	push 	ecx ;; 2nd argument
  4102                              <1> 	;;
  4103 000041F9 E8D9FDFFFF          <1> 	call	namei
  4104                              <1> 		; jsr r0,namei / get its i-number
  4105                              <1>        ; Retro UNIX 8086 v1 modification !
  4106                              <1>        ; ax = 0 -> file not found 
  4107                              <1> 	;and	ax, ax
  4108                              <1> 	;jz	error
  4109                              <1> 	;jc	error ; 27/05/2013
  4110                              <1> 		; br error3
  4111 000041FE 730F                <1> 	jnc	short isown0
  4112                              <1> 	; 'file not found !' error
  4113 00004200 C705[41650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4113 00004208 0000                <1>
  4114 0000420A E9BCEEFFFF          <1> 	jmp	error
  4115                              <1> isown0:
  4116 0000420F E8D3050000          <1> 	call	iget
  4117                              <1> 		; jsr r0,iget / get i-node into core
  4118 00004214 A0[38650000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4119 00004219 08C0                <1> 	or	al, al
  4120                              <1> 		; tstb u.uid / super user?
  4121 0000421B 7417                <1> 	jz	short isown1
  4122                              <1> 		; beq 1f / yes, branch
  4123 0000421D 3A05[E7610000]      <1> 	cmp	al, [i.uid]
  4124                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4125                              <1> 				 ; / the file
  4126                              <1> 	;jne	error
  4127                              <1> 		; beq 1f / yes
  4128                              <1> 		; jmp error3 / no, error
  4129 00004223 740F                <1> 	je	short isown1
  4130                              <1> 
  4131 00004225 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4131 0000422D 0000                <1>
  4132                              <1> 			;  'permission denied !' error
  4133 0000422F E997EEFFFF          <1> 	jmp	error
  4134                              <1> isown1: ; 1:
  4135 00004234 E8B8060000          <1> 	call	setimod
  4136                              <1> 		; jsr r0,setimod / indicates 
  4137                              <1> 		;	       ; / i-node has been modified
  4138 00004239 58                  <1> 	pop	eax ; 2nd argument
  4139                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4140                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4141 0000423A C3                  <1> 	retn
  4142                              <1> 		; rts r0
  4143                              <1> 
  4144                              <1> ;;arg:  ; < get system call arguments >
  4145                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4146                              <1> 	; of form:
  4147                              <1> 	;	sys 'routine' ; arg1
  4148                              <1> 	;		or
  4149                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4150                              <1> 	;		or
  4151                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4152                              <1> 	;	
  4153                              <1> 	; INPUTS ->
  4154                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4155                              <1> 	;	This pointers's value is actually the value of
  4156                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4157                              <1> 	;	made to process the sys instruction
  4158                              <1> 	;    r0 - contains the return address for the routine
  4159                              <1> 	;	that called arg. The data in the word pointer 
  4160                              <1> 	;	to by the return address is used as address
  4161                              <1> 	;	in which the extracted argument is stored   		
  4162                              <1> 	;    	
  4163                              <1> 	; OUTPUTS ->
  4164                              <1> 	;    'address' - contains the extracted argument 
  4165                              <1> 	;    u.sp+18 - is incremented by 2 
  4166                              <1> 	;    r1 - contains the extracted argument
  4167                              <1> 	;    r0 - points to the next instruction to be
  4168                              <1> 	;	 executed in the calling routine.
  4169                              <1> 	;
  4170                              <1>   
  4171                              <1> 	; mov u.sp,r1
  4172                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4173                              <1> 			; / into argument of arg2
  4174                              <1> 	; add $2,18.(r1) / point pc on stack 
  4175                              <1> 			      ; / to next system argument
  4176                              <1> 	; rts r0
  4177                              <1> 
  4178                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4179                              <1> 	; 'arg2' takes first argument in system call
  4180                              <1> 	;  (pointer to name of the file) and puts it in location
  4181                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4182                              <1> 	;  and on top of the stack
  4183                              <1> 	;	
  4184                              <1> 	; INPUTS ->
  4185                              <1> 	;    u.sp, r0
  4186                              <1> 	;    	
  4187                              <1> 	; OUTPUTS ->
  4188                              <1> 	;    u.namep
  4189                              <1> 	;    u.off 
  4190                              <1> 	;    u.off pushed on stack
  4191                              <1> 	;    r1
  4192                              <1> 	;
  4193                              <1> 
  4194                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4195                              <1> 				; / first arg in sys call
  4196                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4197                              <1> 				; / second arg in sys call
  4198                              <1> 	; mov r0,r1 / r0 points to calling routine
  4199                              <1> 	; mov (sp),r0 / put operation code back in r0
  4200                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4201                              <1> 			; / on stack
  4202                              <1> 	; jmp (r1) / return to calling routine
  4203                              <1> 
  4204                              <1> syschown: ; < change owner of file >
  4205                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4206                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4207                              <1> 	;
  4208                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4209                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4210                              <1> 	; changed to 'owner'
  4211                              <1> 	;
  4212                              <1> 	; Calling sequence:
  4213                              <1> 	;	syschown; name; owner
  4214                              <1> 	; Arguments:
  4215                              <1> 	;	name - address of the file name
  4216                              <1> 	;	       terminated by null byte.
  4217                              <1> 	;	owner - (new) owner (number/ID)
  4218                              <1> 	;	
  4219                              <1> 	; Inputs: -
  4220                              <1> 	; Outputs: -
  4221                              <1> 	; ...............................................................
  4222                              <1> 	;				
  4223                              <1> 	; Retro UNIX 8086 v1 modification: 
  4224                              <1> 	;       'syschown' system call has two arguments; so,
  4225                              <1> 	;	* 1st argument, name is pointed to by BX register
  4226                              <1> 	;	* 2nd argument, owner number is in CX register
  4227                              <1> 	;
  4228                              <1> 	; / name; owner
  4229 0000423B E8B2FFFFFF          <1> 	call	isown
  4230                              <1> 		; jsr r0,isown / get the i-node and check user status
  4231 00004240 803D[38650000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4232                              <1> 		; tstb u.uid / super user
  4233 00004247 7418                <1> 	jz	short syschown1
  4234                              <1> 		; beq 2f / yes, 2f
  4235 00004249 F605[E4610000]20    <1>         test    byte [i.flgs], 20h ; 32
  4236                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4237                              <1> 	;jnz	error
  4238                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4239 00004250 740F                <1> 	jz	short syschown1
  4240                              <1> 	; 'permission denied !'
  4241 00004252 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4241 0000425A 0000                <1>
  4242 0000425C E96AEEFFFF          <1> 	jmp	error
  4243                              <1> syschown1: ; 2:
  4244                              <1> 	; AL = owner (number/ID)
  4245 00004261 A2[E7610000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4246                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4247                              <1> 			       ; / in the i-node
  4248 00004266 E980EEFFFF          <1> 	jmp	sysret
  4249                              <1> 	; 1: 
  4250                              <1> 		; jmp sysret4
  4251                              <1> 	; 3:
  4252                              <1> 		; jmp	error
  4253                              <1> 
  4254                              <1> systime: ; / get time of year
  4255                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4256                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4257                              <1> 	;
  4258                              <1> 	; 20/06/2013
  4259                              <1> 	; 'systime' gets the time of the year.
  4260                              <1> 	; The present time is put on the stack.
  4261                              <1> 	;
  4262                              <1> 	; Calling sequence:
  4263                              <1> 	;	systime
  4264                              <1> 	; Arguments: -
  4265                              <1> 	;	
  4266                              <1> 	; Inputs: -
  4267                              <1> 	; Outputs: sp+2, sp+4 - present time
  4268                              <1> 	; ...............................................................
  4269                              <1> 	;	
  4270                              <1> 	; Retro UNIX 8086 v1 modification: 
  4271                              <1> 	;       'systime' system call will return to the user
  4272                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4273                              <1> 	;
  4274                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4275                              <1> 	;	system call for PC compatibility !!		 	
  4276                              <1> 
  4277 0000426B E8ACE9FFFF          <1> 	call 	epoch
  4278 00004270 A3[EC640000]        <1> 	mov 	[u.r0], eax
  4279                              <1> 		; mov s.time,4(sp)
  4280                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4281                              <1> 				   ; / on the stack
  4282                              <1> 		; br sysret4
  4283 00004275 E971EEFFFF          <1> 	jmp	sysret 
  4284                              <1> 
  4285                              <1> sysstime: ; / set time
  4286                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4287                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4288                              <1> 	;
  4289                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4290                              <1> 	;
  4291                              <1> 	; Calling sequence:
  4292                              <1> 	;	sysstime
  4293                              <1> 	; Arguments: -
  4294                              <1> 	;	
  4295                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4296                              <1> 	; Outputs: -
  4297                              <1> 	; ...............................................................
  4298                              <1> 	;	
  4299                              <1> 	; Retro UNIX 8086 v1 modification: 
  4300                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4301                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4302                              <1> 	; 
  4303                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4304                              <1> 	;	to get sysstime system call arguments from the user;
  4305                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4306                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4307                              <1> 	;
  4308                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4309                              <1> 	;	system call for PC compatibility !!	
  4310                              <1> 
  4311 0000427A 803D[38650000]00    <1> 	cmp	byte [u.uid], 0
  4312                              <1> 		; tstb u.uid / is user the super user
  4313                              <1> 	;ja	error
  4314                              <1> 		; bne error4 / no, error
  4315 00004281 760F                <1> 	jna	short systime1
  4316                              <1> 	; 'permission denied !'
  4317 00004283 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4317 0000428B 0000                <1>
  4318 0000428D E939EEFFFF          <1> 	jmp	error
  4319                              <1> systime1:
  4320                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4321                              <1> 	; EBX = unix (epoch) time (from user)
  4322 00004292 89D8                <1> 	mov	eax, ebx
  4323 00004294 E800EBFFFF          <1> 	call 	set_date_time
  4324                              <1> 		; mov 4(sp),s.time
  4325                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4326 00004299 E94DEEFFFF          <1> 	jmp	sysret
  4327                              <1> 		; br sysret4
  4328                              <1> 
  4329                              <1> sysbreak:
  4330                              <1> 	; 18/10/2015
  4331                              <1> 	; 07/10/2015
  4332                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4333                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4334                              <1> 	;
  4335                              <1> 	; 'sysbreak' sets the programs break points. 
  4336                              <1> 	; It checks the current break point (u.break) to see if it is
  4337                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4338                              <1> 	; even address (if it was odd) and the area between u.break
  4339                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4340                              <1> 	; in u.break and control is passed to 'sysret'.
  4341                              <1> 	;
  4342                              <1> 	; Calling sequence:
  4343                              <1> 	;	sysbreak; addr
  4344                              <1> 	; Arguments: -
  4345                              <1> 	;	
  4346                              <1> 	; Inputs: u.break - current breakpoint
  4347                              <1> 	; Outputs: u.break - new breakpoint 
  4348                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4349                              <1> 	; ...............................................................
  4350                              <1> 	;	
  4351                              <1> 	; Retro UNIX 8086 v1 modification:
  4352                              <1> 	;	The user/application program puts breakpoint address
  4353                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4354                              <1> 	; 	(argument transfer method 1)
  4355                              <1> 	;
  4356                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4357                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4358                              <1> 	;  NOTE:
  4359                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4360                              <1> 	;	'u.break' address) of user's memory for original unix's
  4361                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4362                              <1> 
  4363                              <1> 		; mov u.break,r1 / move users break point to r1
  4364                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4365                              <1> 		; blos 1f / yes, 1f
  4366                              <1> 	; 23/06/2015
  4367 0000429E 8B2D[18650000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4368                              <1> 	;and	ebp, ebp
  4369                              <1> 	;jz	short sysbreak_3 
  4370                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4371                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4372 000042A4 8B15[E4640000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4373 000042AA 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4374                              <1> 	; 07/10/2015
  4375 000042AD 891D[18650000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4376                              <1> 	;
  4377 000042B3 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4378                              <1> 			   ; with top of user's stack (virtual!)
  4379 000042B5 7327                <1> 	jnb	short sysbreak_3
  4380                              <1> 		; cmp r1,sp / is it the same or higher 
  4381                              <1> 			  ; / than the stack?
  4382                              <1> 		; bhis 1f / yes, 1f
  4383 000042B7 89DE                <1> 	mov	esi, ebx
  4384 000042B9 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4385 000042BB 7621                <1> 	jna	short sysbreak_3 
  4386                              <1> 	;push	ebx
  4387                              <1> sysbreak_1:
  4388 000042BD 89EB                <1> 	mov	ebx, ebp  
  4389 000042BF E8E5E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4390 000042C4 0F82ABFEFFFF        <1> 	jc	tr_addr_nm_err
  4391                              <1> 	; 18/10/2015
  4392 000042CA 89C7                <1> 	mov	edi, eax 
  4393 000042CC 29C0                <1> 	sub	eax, eax ; 0
  4394                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4395 000042CE 39CE                <1> 	cmp	esi, ecx
  4396 000042D0 7302                <1> 	jnb	short sysbreak_2
  4397 000042D2 89F1                <1> 	mov	ecx, esi
  4398                              <1> sysbreak_2:
  4399 000042D4 29CE                <1> 	sub	esi, ecx
  4400 000042D6 01CD                <1> 	add	ebp, ecx
  4401 000042D8 F3AA                <1> 	rep 	stosb
  4402 000042DA 09F6                <1> 	or	esi, esi
  4403 000042DC 75DF                <1> 	jnz	short sysbreak_1
  4404                              <1> 	;
  4405                              <1> 		; bit $1,r1 / is it an odd address
  4406                              <1> 		; beq 2f / no, its even
  4407                              <1> 		; clrb (r1)+ / yes, make it even
  4408                              <1> 	; 2: / clear area between the break point and the stack
  4409                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4410                              <1> 		; bhis 1f / yes, quit
  4411                              <1> 		; clr (r1)+ / clear word
  4412                              <1> 		; br 2b / go back
  4413                              <1> 	;pop	ebx
  4414                              <1> sysbreak_3: ; 1:
  4415                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4416                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4417                              <1> 			; / in u.break (set new break point)
  4418                              <1> 		; br sysret4 / br sysret
  4419 000042DE E908EEFFFF          <1> 	jmp	sysret
  4420                              <1> 
  4421                              <1> maknod: 
  4422                              <1> 	; 11/02/2022
  4423                              <1> 	; 09/01/2022
  4424                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4425                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4426                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4427                              <1> 	;
  4428                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4429                              <1> 	; for this i-node in the current directory.
  4430                              <1> 	;
  4431                              <1> 	; INPUTS ->
  4432                              <1> 	;    r1 - contains mode
  4433                              <1> 	;    ii - current directory's i-number	
  4434                              <1> 	;    	
  4435                              <1> 	; OUTPUTS ->
  4436                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4437                              <1> 	;    i.flgs - flags in new i-node 
  4438                              <1> 	;    i.uid - filled with u.uid
  4439                              <1> 	;    i.nlks - 1 is put in the number of links
  4440                              <1> 	;    i.ctim - creation time				
  4441                              <1> 	;    i.ctim+2 - modification time
  4442                              <1> 	;    imod - set via call to setimod
  4443                              <1> 	;	
  4444                              <1> 	; ((AX = R1)) input
  4445                              <1> 	;
  4446                              <1> 	; (Retro UNIX Prototype : 
  4447                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4448                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4449                              <1> 
  4450                              <1> 	; / r1 contains the mode
  4451 000042E3 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4452                              <1> 		; bis $100000,r1 / allocate flag set
  4453 000042E6 6650                <1> 	push	ax ; * ; 24/12/2021
  4454                              <1> 		; mov r1,-(sp) / put mode on stack
  4455                              <1> 	; 31/07/2013
  4456 000042E8 66A1[D0640000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4457                              <1> 		; mov ii,r1 / move current i-number to r1
  4458 000042EE B201                <1> 	mov	dl, 1 ; owner flag mask
  4459 000042F0 E8C6050000          <1> 	call	access	
  4460                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4461 000042F5 50                  <1> 	push	eax ; ** ; 24/12/2021
  4462                              <1> 		; mov r1,-(sp) / put i-number on stack
  4463 000042F6 66B82800            <1> 	mov	ax, 40
  4464                              <1> 		; mov $40.,r1 / r1 = 40
  4465                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4466 000042FA 6640                <1> 	inc	ax
  4467                              <1> 		; inc r1 / r1 = r1 + 1
  4468 000042FC E87F060000          <1> 	call	imap
  4469                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4470                              <1> 			    ; /	inode map in r2 & m
  4471                              <1>   
  4472                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4473                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4474                              <1> 
  4475                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4476                              <1> 	;	       Inode count must be checked here
  4477                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4478                              <1> 
  4479                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4480                              <1> 	; (inode count check)
  4481                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4482                              <1> 
  4483 00004301 730F                <1> 	jnc	short maknod2
  4484                              <1> 
  4485                              <1> 	; no free inode in inode table !
  4486 00004303 C705[41650000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4486 0000430B 0000                <1>
  4487                              <1> 			; miscellaneous/other errors
  4488 0000430D E9B9EDFFFF          <1> 	jmp	error	
  4489                              <1> maknod2: 
  4490 00004312 8413                <1> 	test	[ebx], dl
  4491                              <1> 		; bitb mq,(r2) / is the i-node active
  4492 00004314 75E4                <1> 	jnz	short maknod1
  4493                              <1> 		; bne 1b / yes, try the next one
  4494 00004316 0813                <1> 	or	[ebx], dl
  4495                              <1> 		; bisb mq,(r2) / no, make it active 
  4496                              <1> 			     ; / (put a 1 in the bit map)
  4497 00004318 E8CA040000          <1> 	call	iget
  4498                              <1> 		; jsr r0,iget / get i-node into core
  4499                              <1> 	; 09/01/2022
  4500 0000431D F605[E5610000]80    <1> 	test	byte [i.flgs+1], 80h
  4501                              <1> 	;test	word [i.flgs], 8000h 
  4502                              <1> 		; tst i.flgs / is i-node already allocated
  4503 00004324 75D4                <1> 	jnz	short maknod1	
  4504                              <1> 		; blt 1b / yes, look for another one
  4505 00004326 66A3[1E650000]      <1> 	mov	[u.dirbuf], ax
  4506                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4507 0000432C 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4508                              <1> 		; mov (sp)+,r1 / get current i-number back
  4509 0000432D E8B5040000          <1> 	call	iget
  4510                              <1> 		; jsr r0,iget / get i-node in core
  4511 00004332 E857F7FFFF          <1> 	call	mkdir
  4512                              <1> 		; jsr r0,mkdir / make a directory entry 
  4513                              <1> 			     ; / in current directory
  4514 00004337 66A1[1E650000]      <1> 	mov	ax, [u.dirbuf]
  4515                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4516 0000433D E8A5040000          <1> 	call	iget
  4517                              <1> 		; jsr r0,iget / get it into core
  4518                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4519                              <1> 	;mov	ecx, 8
  4520                              <1> 	; 09/01/2022 
  4521 00004342 29C9                <1> 	sub	ecx, ecx
  4522 00004344 B108                <1> 	mov	cl, 8
  4523 00004346 31C0                <1> 	xor	eax, eax ; 0
  4524 00004348 BF[E4610000]        <1> 	mov	edi, inode 
  4525 0000434D F3AB                <1> 	rep	stosd
  4526                              <1> 	;
  4527 0000434F 668F05[E4610000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4528                              <1> 		; mov (sp)+,i.flgs / fill flags
  4529 00004356 8A0D[38650000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4530 0000435C 880D[E7610000]      <1> 	mov 	[i.uid], cl
  4531                              <1> 		; movb u.uid,i.uid / user id	
  4532 00004362 C605[E6610000]01    <1> 	mov     byte [i.nlks], 1
  4533                              <1> 		; movb $1,i.nlks / 1 link
  4534                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4535                              <1> 	;mov	eax, [s.time]
  4536                              <1> 	;mov 	[i.ctim], eax
  4537                              <1> 	 	; mov s.time,i.ctim / time created
  4538                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4539                              <1> 	; Retro UNIX 8086 v1 modification !
  4540                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4541                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4542                              <1> 	;call	setimod
  4543                              <1> 	;	; jsr r0,setimod / set modified flag
  4544                              <1> 	;retn
  4545                              <1> 	;	; rts r0 / return
  4546                              <1> 	; 24/12/2021
  4547 00004369 E983050000          <1> 	jmp	setimod
  4548                              <1> 
  4549                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4550                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4551                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4552                              <1> 	;
  4553                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4554                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4555                              <1> 	; The file descriptor refers to a file open for reading or
  4556                              <1> 	; writing. The read (or write) pointer is set as follows:
  4557                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4558                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4559                              <1> 	;	  current location plus offset.
  4560                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4561                              <1> 	;	  size of file plus offset.
  4562                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4563                              <1> 	;
  4564                              <1> 	; Calling sequence:
  4565                              <1> 	;	sysseek; offset; ptrname
  4566                              <1> 	; Arguments:
  4567                              <1> 	;	offset - number of bytes desired to move 
  4568                              <1> 	;		 the r/w pointer
  4569                              <1> 	;	ptrname - a switch indicated above
  4570                              <1> 	;
  4571                              <1> 	; Inputs: r0 - file descriptor 
  4572                              <1> 	; Outputs: -
  4573                              <1> 	; ...............................................................
  4574                              <1> 	;	
  4575                              <1> 	; Retro UNIX 8086 v1 modification: 
  4576                              <1> 	;       'sysseek' system call has three arguments; so,
  4577                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4578                              <1> 	;	* 2nd argument, offset is in CX register
  4579                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4580                              <1> 	;	
  4581                              <1> 
  4582 0000436E E822000000          <1> 	call	seektell
  4583                              <1> 	; AX = u.count
  4584                              <1> 	; BX = *u.fofp
  4585                              <1> 		; jsr r0,seektell / get proper value in u.count
  4586                              <1> 		; add u.base,u.count / add u.base to it
  4587 00004373 0305[0C650000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4588 00004379 8903                <1> 	mov	[ebx], eax
  4589                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4590 0000437B E96BEDFFFF          <1> 	jmp	sysret
  4591                              <1> 		; br sysret4
  4592                              <1> 
  4593                              <1> systell: ; / get the r/w pointer
  4594                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4595                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4596                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4597                              <1> 	;
  4598                              <1> 	; Retro UNIX 8086 v1 modification:
  4599                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4600                              <1> 	; 	    it returns with error !
  4601                              <1> 	; Inputs: r0 - file descriptor 
  4602                              <1> 	; Outputs: r0 - file r/w pointer
  4603                              <1> 
  4604                              <1> 	;xor	ecx, ecx ; 0
  4605                              <1> 	;mov	edx, 1 ; 05/08/2013
  4606                              <1> 	; 24/12/2021
  4607 00004380 29D2                <1> 	sub	edx, edx
  4608 00004382 FEC2                <1> 	inc	dl
  4609                              <1> 	; edx = 1
  4610                              <1> 	;call 	seektell
  4611 00004384 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4612                              <1> 	;mov	ebx, [u.fofp]
  4613 00004389 8B03                <1> 	mov	eax, [ebx]
  4614 0000438B A3[EC640000]        <1> 	mov	[u.r0], eax
  4615 00004390 E956EDFFFF          <1> 	jmp	sysret
  4616                              <1> 
  4617                              <1> ; Original unix v1 'systell' system call:
  4618                              <1> 		; jsr r0,seektell
  4619                              <1> 		; br error4
  4620                              <1> 
  4621                              <1> seektell:
  4622                              <1> 	; 03/02/2022
  4623                              <1> 	; 03/01/2016
  4624                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4625                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4626                              <1> 	;
  4627                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4628                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4629                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4630                              <1> 	; getf. The i-node is brought into core and then u.count
  4631                              <1> 	; is checked to see it is a 0, 1, or 2.
  4632                              <1> 	; If it is 0 - u.count stays the same
  4633                              <1> 	;          1 - u.count = offset (u.fofp)
  4634                              <1> 	;	   2 - u.count = i.size (size of file)
  4635                              <1> 	; 	 		
  4636                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4637                              <1> 	;	Argument 1, file descriptor is in BX;
  4638                              <1> 	;	Argument 2, offset is in CX;
  4639                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4640                              <1> 	;
  4641                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4642                              <1> 	; call 	arg
  4643                              <1> 	;
  4644                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4645                              <1> 	;
  4646 00004395 890D[0C650000]      <1> 	mov 	[u.base], ecx ; offset
  4647                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4648                              <1> seektell0:
  4649 0000439B 8915[10650000]      <1> 	mov 	[u.count], edx
  4650                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4651                              <1> 	; mov	ax, bx
  4652                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4653                              <1> 			     ; / (index in u.fp list)
  4654                              <1> 	; call	getf
  4655                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4656                              <1> 	; BX = file descriptor (file number)
  4657 000043A1 E800FCFFFF          <1> 	call	getf1
  4658                              <1> 	; 03/02/2022
  4659 000043A6 09C0                <1> 	or	eax, eax
  4660                              <1> 	;or	ax, ax ; i-number of the file
  4661                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4662                              <1> 		             ; / put it on the stack
  4663                              <1> 	;jz	error
  4664                              <1> 		; beq error4 / if i-number is 0, not active so error
  4665 000043A8 750F                <1> 	jnz	short seektell1
  4666 000043AA C705[41650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4666 000043B2 0000                <1>
  4667 000043B4 E912EDFFFF          <1> 	jmp	error
  4668                              <1> seektell1:
  4669                              <1> 	;push	eax
  4670 000043B9 80FC80              <1> 	cmp	ah, 80h
  4671 000043BC 7203                <1> 	jb	short seektell2
  4672                              <1> 		; bgt .+4 / if its positive jump
  4673 000043BE 66F7D8              <1> 	neg	ax
  4674                              <1> 		; neg r1 / if not make it positive
  4675                              <1> seektell2:
  4676 000043C1 E821040000          <1> 	call	iget
  4677                              <1> 		; jsr r0,iget / get its i-node into core
  4678 000043C6 8B1D[FC640000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4679 000043CC 803D[10650000]01    <1> 	cmp	byte [u.count], 1
  4680                              <1> 		; cmp u.count,$1 / is ptr name =1
  4681 000043D3 7705                <1> 	ja	short seektell3
  4682                              <1> 		; blt 2f / no its zero
  4683 000043D5 740A                <1> 	je	short seektell_4
  4684                              <1> 		; beq 1f / yes its 1
  4685 000043D7 31C0                <1> 	xor	eax, eax
  4686                              <1> 	;jmp	short seektell_5
  4687 000043D9 C3                  <1> 	retn
  4688                              <1> seektell3:
  4689                              <1> 	; 03/01/2016
  4690                              <1> 	;movzx	eax, word [i.size]
  4691 000043DA 66A1[E8610000]      <1>         mov   	ax, [i.size]
  4692                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4693                              <1>                                    ; / in file in u.count
  4694                              <1> 	;jmp	short seektell_5
  4695                              <1> 		; br 2f
  4696 000043E0 C3                  <1> 	retn
  4697                              <1> seektell_4: ; 1: / ptrname =1
  4698                              <1> 	;mov	ebx, [u.fofp]
  4699 000043E1 8B03                <1> 	mov	eax, [ebx]
  4700                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4701                              <1> ;seektell_5: ; 2: / ptrname =0
  4702                              <1> 	;mov	[u.count], eax
  4703                              <1> 	;pop	eax 
  4704                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4705 000043E3 C3                  <1> 	retn
  4706                              <1> 		; rts r0
  4707                              <1> 
  4708                              <1> sysintr: ; / set interrupt handling
  4709                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4710                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4711                              <1> 	;
  4712                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4713                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4714                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4715                              <1> 	; If one does the interrupt character in the tty buffer is
  4716                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4717                              <1> 	; 'sysret' is just called.	
  4718                              <1> 	;
  4719                              <1> 	; Calling sequence:
  4720                              <1> 	;	sysintr; arg
  4721                              <1> 	; Argument:
  4722                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4723                              <1> 	;	    - if 1, intterupts cause their normal result
  4724                              <1> 	;		 i.e force an exit.
  4725                              <1> 	;	    - if arg is a location within the program,
  4726                              <1> 	;		control is passed to that location when
  4727                              <1> 	;		an interrupt occurs.	
  4728                              <1> 	; Inputs: -
  4729                              <1> 	; Outputs: -
  4730                              <1> 	; ...............................................................
  4731                              <1> 	;	
  4732                              <1> 	; Retro UNIX 8086 v1 modification: 
  4733                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4734                              <1> 	;	then branches into sysquit.
  4735                              <1> 	;
  4736 000043E4 66891D[30650000]    <1> 	mov	[u.intr], bx
  4737                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4738                              <1> 		; br 1f / go into quit routine
  4739 000043EB E9FBECFFFF          <1> 	jmp	sysret
  4740                              <1> 
  4741                              <1> sysquit:
  4742                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4743                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4744                              <1> 	;
  4745                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4746                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4747                              <1> 	; tty exists. If one does the interrupt character in the tty
  4748                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4749                              <1> 	; 'sysret' is just called.	
  4750                              <1> 	;
  4751                              <1> 	; Calling sequence:
  4752                              <1> 	;	sysquit; arg
  4753                              <1> 	; Argument:
  4754                              <1> 	;	arg - if 0, this call diables quit signals from the
  4755                              <1> 	;		typewriter (ASCII FS)
  4756                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4757                              <1> 	;		cease and a core image to be produced.
  4758                              <1> 	;		 i.e force an exit.
  4759                              <1> 	;	    - if arg is an addres in the program,
  4760                              <1> 	;		a quit causes control to sent to that
  4761                              <1> 	;		location.	
  4762                              <1> 	; Inputs: -
  4763                              <1> 	; Outputs: -
  4764                              <1> 	; ...............................................................
  4765                              <1> 	;	
  4766                              <1> 	; Retro UNIX 8086 v1 modification: 
  4767                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4768                              <1> 	;	then branches into 'sysret'.
  4769                              <1> 	;
  4770 000043F0 66891D[32650000]    <1> 	mov	[u.quit], bx
  4771 000043F7 E9EFECFFFF          <1> 	jmp	sysret
  4772                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4773                              <1> 	;1:
  4774                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4775                              <1> 			      ; / to r1
  4776                              <1> 		; beq sysret4 / return to user
  4777                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4778                              <1> 			   ; / in the tty buffer
  4779                              <1> 		; br sysret4 / return to user
  4780                              <1> 
  4781                              <1> syssetuid: ; / set process id
  4782                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4783                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4784                              <1> 	;
  4785                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4786                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4787                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4788                              <1> 	; Only the super user can make this call.	
  4789                              <1> 	;
  4790                              <1> 	; Calling sequence:
  4791                              <1> 	;	syssetuid
  4792                              <1> 	; Arguments: -
  4793                              <1> 	;
  4794                              <1> 	; Inputs: (u.r0) - contains the process id.
  4795                              <1> 	; Outputs: -
  4796                              <1> 	; ...............................................................
  4797                              <1> 	;	
  4798                              <1> 	; Retro UNIX 8086 v1 modification: 
  4799                              <1> 	;       BL contains the (new) user ID of the current process
  4800                              <1> 
  4801                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4802 000043FC 3A1D[39650000]      <1> 	cmp	bl, [u.ruid] 
  4803                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4804                              <1> 			       ; / id number
  4805 00004402 741E                <1> 	je	short setuid1
  4806                              <1> 		; beq 1f / yes
  4807 00004404 803D[38650000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4808                              <1> 		; tstb u.uid / no, is current user the super user?
  4809                              <1> 	;ja	error
  4810                              <1> 		; bne error4 / no, error
  4811 0000440B 760F                <1> 	jna	short setuid0
  4812 0000440D C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4812 00004415 0000                <1>
  4813                              <1> 				; 'permission denied !' error
  4814 00004417 E9AFECFFFF          <1> 	jmp	error
  4815                              <1> setuid0:
  4816 0000441C 881D[39650000]      <1> 	mov	[u.ruid], bl
  4817                              <1> setuid1: ; 1:
  4818 00004422 881D[38650000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4819                              <1> 		; movb r1,u.uid / put process id in u.uid
  4820                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4821 00004428 E9BEECFFFF          <1> 	jmp	sysret
  4822                              <1> 		; br sysret4 / system return
  4823                              <1> 
  4824                              <1> sysgetuid: ; < get user id >
  4825                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4826                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4827                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4828                              <1> 	;
  4829                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4830                              <1> 	; The real user ID identifies the person who is logged in,
  4831                              <1> 	; in contradistinction to the effective user ID, which
  4832                              <1> 	; determines his access permission at each moment. It is thus
  4833                              <1> 	; useful to programs which operate using the 'set user ID'
  4834                              <1> 	; mode, to find out who invoked them.	
  4835                              <1> 	;
  4836                              <1> 	; Calling sequence:
  4837                              <1> 	;	syssetuid
  4838                              <1> 	; Arguments: -
  4839                              <1> 	;
  4840                              <1> 	; Inputs: -
  4841                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4842                              <1> 	; ...............................................................
  4843                              <1> 	;	
  4844                              <1> 	; Retro UNIX 8086 v1 modification: 
  4845                              <1> 	;       AL contains the real user ID at return.
  4846                              <1> 	;
  4847                              <1> 	;movzx 	eax, byte [u.ruid]
  4848                              <1> 	; 09/01/2022
  4849 0000442D A0[39650000]        <1> 	mov	al, [u.ruid]
  4850 00004432 A3[EC640000]        <1> 	mov	[u.r0], eax
  4851                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4852 00004437 E9AFECFFFF          <1> 	jmp	sysret
  4853                              <1> 		; br sysret4 / systerm return, sysret
  4854                              <1> 
  4855                              <1> anyi: 
  4856                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4857                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4858                              <1> 	;
  4859                              <1> 	; 'anyi' is called if a file deleted while open.
  4860                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4861                              <1> 	;
  4862                              <1> 	; INPUTS ->
  4863                              <1> 	;    r1 - contains an i-number
  4864                              <1> 	;    fsp - start of table containing open files
  4865                              <1> 	;
  4866                              <1> 	; OUTPUTS ->
  4867                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4868                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4869                              <1> 	;    if file not found - bit in i-node map is cleared
  4870                              <1> 	;    			 (i-node is freed)
  4871                              <1> 	;               all blocks related to i-node are freed
  4872                              <1> 	;	        all flags in i-node are cleared
  4873                              <1> 	; ((AX = R1)) input
  4874                              <1> 	;
  4875                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4876                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4877                              <1> 	;
  4878                              <1> 		; / r1 contains an i-number
  4879 0000443C BB[B4620000]        <1> 	mov	ebx, fsp
  4880                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4881                              <1> anyi_1: ; 1:
  4882 00004441 663B03              <1> 	cmp	ax, [ebx]
  4883                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4884 00004444 7433                <1> 	je	short anyi_3
  4885                              <1> 		; beq 1f / yes, 1f
  4886 00004446 66F7D8              <1> 	neg	ax
  4887                              <1> 		; neg r1 / no complement r1
  4888 00004449 663B03              <1> 	cmp	ax, [ebx]
  4889                              <1> 		; cmp r1,(r2) / do they match now?
  4890 0000444C 742B                <1> 	je	short anyi_3
  4891                              <1> 		; beq 1f / yes, transfer
  4892                              <1> 		; / i-numbers do not match
  4893 0000444E 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4894                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4895                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4896 00004451 81FB[A8640000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4897                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4898                              <1> 				; / are we at last entry in the table
  4899 00004457 72E8                <1> 	jb	short anyi_1
  4900                              <1> 		; blt 1b / no, check next entries i-number
  4901                              <1> 	;cmp	ax, 32768
  4902 00004459 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4903                              <1> 		; tst r1 / yes, no match
  4904                              <1> 		; bge .+4
  4905 0000445C 7203                <1> 	jb	short anyi_2
  4906 0000445E 66F7D8              <1> 	neg	ax
  4907                              <1> 		; neg r1 / make i-number positive
  4908                              <1> anyi_2:	
  4909 00004461 E81A050000          <1> 	call	imap
  4910                              <1> 		; jsr r0,imap / get address of allocation bit 
  4911                              <1> 			    ; / in the i-map in r2
  4912                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4913                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4914                              <1>  	; not	dx
  4915 00004466 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4916                              <1>         ;and	[ebx], dx
  4917 00004468 2013                <1> 	and 	[ebx], dl 
  4918                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4919 0000446A E8A4040000          <1> 	call	itrunc
  4920                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4921 0000446F 66C705[E4610000]00- <1>  	mov 	word [i.flgs], 0
  4921 00004477 00                  <1>
  4922                              <1> 		; clr i.flgs / clear all flags in the i-node
  4923 00004478 C3                  <1> 	retn
  4924                              <1> 		;rts	r0 / return
  4925                              <1> anyi_3: ; 1: / i-numbers match
  4926 00004479 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4927                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4928                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4929 0000447C C3                  <1> 	retn
  4930                              <1> 		; rts r0
  2116                                  %include 'u3.s'        ; 10/05/2015
  2117                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2118                              <1> ; Last Modification: 24/12/2021
  2119                              <1> ; ----------------------------------------------------------------------------
  2120                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2121                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2122                              <1> ;
  2123                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2124                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2125                              <1> ; <Bell Laboratories (17/3/1972)>
  2126                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2127                              <1> ;
  2128                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2129                              <1> ;
  2130                              <1> ; ****************************************************************************
  2131                              <1> 
  2132                              <1> tswitch: ; Retro UNIX 386 v1
  2133                              <1> tswap:
  2134                              <1> 	; 01/09/2015
  2135                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2136                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2137                              <1> 	; time out swap, called when a user times out.
  2138                              <1> 	; the user is put on the low priority queue.
  2139                              <1> 	; This is done by making a link from the last user
  2140                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2141                              <1> 	; then he is swapped out.
  2142                              <1> 	;
  2143                              <1> 	; Retro UNIX 386 v1 modification ->
  2144                              <1> 	;       swap (software task switch) is performed by changing
  2145                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2146                              <1> 	;	as in Retro UNIX 8086 v1.
  2147                              <1> 	;
  2148                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2149                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2150                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2151                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2152                              <1> 	;	compatibles was using 1MB segmented memory 
  2153                              <1> 	;	in 8086/8088 times.
  2154                              <1> 	;
  2155                              <1> 	; INPUTS ->
  2156                              <1> 	;    u.uno - users process number
  2157                              <1> 	;    runq+4 - lowest priority queue
  2158                              <1> 	; OUTPUTS ->
  2159                              <1> 	;    r0 - users process number
  2160                              <1> 	;    r2 - lowest priority queue address
  2161                              <1> 	;
  2162                              <1> 	; ((AX = R0, BX = R2)) output
  2163                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2164                              <1> 	;
  2165 0000447D A0[3B650000]        <1> 	mov 	al, [u.uno]
  2166                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2167                              <1> 		; mov  $runq+4,r2 
  2168                              <1> 			; / move lowest priority queue address to r2
  2169 00004482 E8CD000000          <1>         call 	putlu
  2170                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2171                              <1> 		             ; / u.uno's user
  2172                              <1> 
  2173                              <1> switch: ; Retro UNIX 386 v1
  2174                              <1> swap:
  2175                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2176                              <1> 	; 02/09/2015
  2177                              <1> 	; 01/09/2015
  2178                              <1> 	; 31/08/2015
  2179                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2180                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2181                              <1> 	; 'swap' is routine that controls the swapping of processes
  2182                              <1> 	; in and out of core.
  2183                              <1> 	;
  2184                              <1> 	; Retro UNIX 386 v1 modification ->
  2185                              <1> 	;       swap (software task switch) is performed by changing
  2186                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2187                              <1> 	;	as in Retro UNIX 8086 v1.
  2188                              <1> 	;
  2189                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2190                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2191                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2192                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2193                              <1> 	;	compatibles was using 1MB segmented memory 
  2194                              <1> 	;	in 8086/8088 times.
  2195                              <1> 	;
  2196                              <1> 	; INPUTS ->
  2197                              <1> 	;    runq table - contains processes to run.
  2198                              <1> 	;    p.link - contains next process in line to be run.
  2199                              <1> 	;    u.uno - process number of process in core	
  2200                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2201                              <1> 	; OUTPUTS ->
  2202                              <1> 	;    (original unix v1 -> present process to its disk block)
  2203                              <1> 	;    (original unix v1 -> new process into core -> 
  2204                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2205                              <1> 	;	   for new process)
  2206                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2207                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2208                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2209                              <1> 	;	 for now, it will swap the process if there is not
  2210                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2211                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2212                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2213                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2214                              <1> 	;
  2215                              <1> 	;    u.pri -points to highest priority run Q.
  2216                              <1> 	;    r2 - points to the run queue.
  2217                              <1> 	;    r1 - contains new process number
  2218                              <1> 	;    r0 - points to place in routine or process that called
  2219                              <1> 	;	  swap all user parameters
  2220                              <1> 	;				
  2221                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2222                              <1> 	;
  2223                              <1> swap_0:
  2224                              <1> 		;mov $300,*$ps / processor priority = 6
  2225 00004487 BE[DE640000]        <1> 	mov	esi, runq
  2226                              <1> 		; mov $runq,r2 / r2 points to runq table
  2227                              <1> swap_1: ; 1: / search runq table for highest priority process
  2228 0000448C 668B06              <1> 	mov	ax, [esi]
  2229 0000448F 6621C0              <1> 	and 	ax, ax
  2230                              <1>        		; tst (r2)+ / are there any processes to run 
  2231                              <1> 			  ; / in this Q entry
  2232 00004492 7507                <1> 	jnz	short swap_2
  2233                              <1>        		; bne 1f / yes, process 1f
  2234                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2235                              <1> 			       ; / to end of table
  2236                              <1> 		; bne 1b / if not at end, go back
  2237 00004494 E8E0000000          <1> 	call	idle
  2238                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2239                              <1> 				       ; / all queues are empty
  2240 00004499 EBF1                <1> 	jmp	short swap_1
  2241                              <1> 		; br swap
  2242                              <1> swap_2: ; 1:
  2243 0000449B 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2244                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2245                              <1>  		; mov r2,u.pri / set present user to this run queue
  2246                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2247 0000449E 38E0                <1> 	cmp	al, ah
  2248                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2249                              <1> 			      ; / in this Q to be run
  2250 000044A0 740A                <1> 	je	short swap_3
  2251                              <1>        		; beq 1f / yes
  2252                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2253                              <1> 	;movzx	ebx, al
  2254 000044A2 8AA3[53620000]      <1> 	mov	ah, [ebx+p.link-1] 
  2255 000044A8 8826                <1>        	mov	[esi], ah
  2256                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2257                              <1> 				       ; / in line into run queue
  2258 000044AA EB05                <1> 	jmp	short swap_4
  2259                              <1>        		; br 2f
  2260                              <1> swap_3: ; 1:
  2261                              <1> 	;xor	dx, dx
  2262                              <1> 	; 24/12/2021
  2263 000044AC 31D2                <1> 	xor	edx, edx
  2264 000044AE 668916              <1> 	mov	[esi], dx
  2265                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2266                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2267                              <1>       ; / in new process if required
  2268                              <1>        		; clr *$ps / clear processor status
  2269 000044B1 8A25[3B650000]      <1> 	mov 	ah, [u.uno]
  2270 000044B7 38C4                <1> 	cmp	ah, al
  2271                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2272                              <1> 			      ; / the process in core?
  2273 000044B9 743B                <1>        	je	short swap_8
  2274                              <1>        		; beq 2f / yes, don't have to swap
  2275                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2276                              <1> 			   ; / (address in routine that called swap)
  2277                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2278                              <1> 	; 01/09/2015
  2279                              <1> 	;mov	[u.usp], esp
  2280                              <1>        		; mov sp,u.usp / save stack pointer
  2281                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2282                              <1> 			       ; / to the stack pointer
  2283 000044BB 08E4                <1> 	or	ah, ah
  2284                              <1>        		; tstb u.uno / is the process # = 0
  2285 000044BD 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2286                              <1> 		; beq 1f / yes, kill process by overwriting
  2287                              <1> 	; 02/09/2015
  2288 000044BF 8925[E8640000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2289                              <1> 	;
  2290 000044C5 E834000000          <1> 	call	wswap
  2291                              <1> 		; jsr r0,wswap / write out core to disk
  2292                              <1> 	 ; 31/08/2015
  2293                              <1> 	;movzx	ebx, al ; New (running) process number
  2294 000044CA EB1C                <1> 	jmp 	short swap_7
  2295                              <1> swap_6:
  2296                              <1> 	; 31/08/2015
  2297                              <1> 	; Deallocate memory pages belong to the process
  2298                              <1> 	; which is being terminated
  2299                              <1> 	; 14/05/2015 ('sysexit')
  2300                              <1>  	; Deallocate memory pages of the process
  2301                              <1> 	; (Retro UNIX 386 v1 modification !)
  2302                              <1> 	;
  2303                              <1> 	; movzx ebx, al
  2304 000044CC 53                  <1> 	push	ebx
  2305 000044CD A1[45650000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2306 000044D2 8B1D[49650000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2307 000044D8 E814E0FFFF          <1> 	call	deallocate_page_dir
  2308 000044DD A1[3C650000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2309 000044E2 E8A0E0FFFF          <1> 	call	deallocate_page
  2310 000044E7 5B                  <1> 	pop	ebx
  2311                              <1> swap_7: ;1: 
  2312                              <1> 	; 02/09/2015
  2313                              <1> 	; 31/08/2015
  2314                              <1> 	; 14/05/2015
  2315 000044E8 C0E302              <1> 	shl	bl, 2 ; * 4 
  2316 000044EB 8B83[70620000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2317                              <1> 	;cli
  2318 000044F1 E831000000          <1> 	call	rswap
  2319                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2320                              <1> 		; jsr r0,rswap / read new process into core
  2321                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2322                              <1> 			      ; / to his program to its normal
  2323                              <1> 	; 01/09/2015
  2324                              <1> 	;mov	esp, [u.usp]	
  2325                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2326                              <1> 			     ; / new process stack
  2327                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2328                              <1> 			     ; / that just got swapped in, left off.,
  2329                              <1> 			     ; / i.e., transfer control to new process
  2330                              <1> 	;sti
  2331                              <1> swap_8: ;2:
  2332                              <1> 	; RETRO UNIX 8086 v1 modification !
  2333 000044F6 C605[2E650000]04    <1> 	mov	byte [u.quant], time_count 
  2334                              <1> 		; movb $30.,uquant / initialize process time quantum
  2335 000044FD C3                  <1> 	retn
  2336                              <1> 		; rts r0 / return
  2337                              <1> 
  2338                              <1> wswap:  ; < swap out, swap to disk >
  2339                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2340                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2341                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2342                              <1> 	; appropriate disk area.
  2343                              <1> 	;
  2344                              <1> 	; Retro UNIX 386 v1 modification ->
  2345                              <1> 	;       User (u) structure content and the user's register content
  2346                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2347                              <1> 	;	saving 'u' structure and user registers for task switching).
  2348                              <1> 	;	u.usp - points to kernel stack address which contains
  2349                              <1> 	;		user's registers while entering system call.  
  2350                              <1> 	;	u.sp  - points to kernel stack address 
  2351                              <1> 	;		to return from system call -for IRET-.
  2352                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2353                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2354                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2355                              <1> 	;
  2356                              <1> 	; Retro UNIX 8086 v1 modification ->
  2357                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2358                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2359                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2360                              <1> 	;	compatibles was using 1MB segmented memory 
  2361                              <1> 	;	in 8086/8088 times.
  2362                              <1> 	;
  2363                              <1> 	; INPUTS ->
  2364                              <1> 	;    u.break - points to end of program
  2365                              <1> 	;    u.usp - stack pointer at the moment of swap
  2366                              <1> 	;    core - beginning of process program		
  2367                              <1> 	;    ecore - end of core 	
  2368                              <1> 	;    user - start of user parameter area		
  2369                              <1> 	;    u.uno - user process number	
  2370                              <1> 	;    p.dska - holds block number of process	
  2371                              <1> 	; OUTPUTS ->
  2372                              <1> 	;    swp I/O queue
  2373                              <1> 	;    p.break - negative word count of process 
  2374                              <1> 	;    r1 - process disk address	
  2375                              <1> 	;    r2 - negative word count
  2376                              <1> 	;
  2377                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2378                              <1> 	;
  2379                              <1> 	; INPUTS ->
  2380                              <1> 	;    u.uno - process number (to be swapped out)
  2381                              <1> 	; OUTPUTS ->
  2382                              <1> 	;    none
  2383                              <1> 	;
  2384                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2385                              <1> 	;
  2386 000044FE 8B3D[3C650000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2387 00004504 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2388 00004509 BE[E4640000]        <1> 	mov	esi, user ; active user (u) structure	
  2389 0000450E F3A5                <1> 	rep	movsd
  2390                              <1> 	;
  2391 00004510 8B35[E8640000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2392                              <1> 			     ;      points to user registers)
  2393 00004516 8B0D[E4640000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2394                              <1> 			     ; (for IRET)
  2395                              <1> 			     ; [u.sp] -> EIP (user)
  2396                              <1> 			     ; [u.sp+4]-> CS (user)
  2397                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2398                              <1> 			     ; [u.sp+12] -> ESP (user)
  2399                              <1> 			     ; [u.sp+16] -> SS (user)	
  2400 0000451C 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2401 0000451E 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2402                              <1> 			     ; (for IRET) 	
  2403 00004521 C1E902              <1> 	shr	ecx, 2	     		
  2404 00004524 F3A5                <1> 	rep	movsd
  2405 00004526 C3                  <1> 	retn
  2406                              <1> 
  2407                              <1> 	; Original UNIX v1 'wswap' routine:
  2408                              <1> 	; wswap:
  2409                              <1> 		; mov *$30,u.emt / determines handling of emts
  2410                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2411                              <1> 				; / illegal instructions
  2412                              <1> 		; mov u.break,r2 / put process program break address in r2
  2413                              <1> 		; inc r2 / add 1 to it 
  2414                              <1> 		; bic $1,r2 / make it even
  2415                              <1> 		; mov r2,u.break / set break to an even location
  2416                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2417                              <1> 			     ; / at moment of swap in r3
  2418                              <1> 		; cmp r2,$core / is u.break less than $core
  2419                              <1> 		; blos 2f / yes
  2420                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2421                              <1>        		; bhis 2f / yes
  2422                              <1> 	; 1:
  2423                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2424                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2425                              <1> 		; bne 1b / no, keep packing
  2426                              <1> 	 	; br 1f / yes
  2427                              <1> 	; 2:
  2428                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2429                              <1> 	; 1:
  2430                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2431                              <1> 			   ; / (user up to end of stack gets written out)
  2432                              <1> 		; neg r2 / make it negative
  2433                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2434                              <1> 		; mov r2,swp+4 / word count
  2435                              <1> 		; movb u.uno,r1 / move user process number to r1
  2436                              <1> 		; asl r1 / x2 for index
  2437                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2438                              <1> 				     ; / into the p.break table
  2439                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2440                              <1> 				    ; /	for process to r1
  2441                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2442                              <1> 			     ; / (block number)
  2443                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2444                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2445                              <1> 	; 1:
  2446                              <1>        		; tstb swp+1 / is lt done writing?
  2447                              <1>        		; bne 1b / no, wait
  2448                              <1> 		; rts r0 / yes, return to swap
  2449                              <1> 
  2450                              <1> rswap:  ; < swap in, swap from disk >
  2451                              <1> 	; 15/09/2015
  2452                              <1> 	; 28/08/2015
  2453                              <1> 	; 14/05/2015
  2454                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2455                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2456                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2457                              <1> 	; from disk into core.
  2458                              <1> 	;
  2459                              <1> 	; Retro UNIX 386 v1 modification ->
  2460                              <1> 	;       User (u) structure content and the user's register content
  2461                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2462                              <1> 	;	saving 'u' structure and user registers for task switching).
  2463                              <1> 	;	u.usp - points to kernel stack address which contains
  2464                              <1> 	;		user's registers while entering system call.  
  2465                              <1> 	;	u.sp  - points to kernel stack address 
  2466                              <1> 	;		to return from system call -for IRET-.
  2467                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2468                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2469                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2470                              <1> 	;
  2471                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2472                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2473                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2474                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2475                              <1> 	;	compatibles was using 1MB segmented memory 
  2476                              <1> 	;	in 8086/8088 times.
  2477                              <1> 	;
  2478                              <1> 	; INPUTS ->
  2479                              <1> 	;    r1 - process number of process to be read in
  2480                              <1> 	;    p.break - negative of word count of process 
  2481                              <1> 	;    p.dska - disk address of the process		
  2482                              <1> 	;    u.emt - determines handling of emt's 	
  2483                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2484                              <1> 	; OUTPUTS ->
  2485                              <1> 	;    8 = (u.ilgins)
  2486                              <1> 	;    24 = (u.emt)
  2487                              <1> 	;    swp - bit 10 is set to indicate read 
  2488                              <1> 	;		(bit 15=0 when reading is done)	
  2489                              <1> 	;    swp+2 - disk block address
  2490                              <1> 	;    swp+4 - negative word count 	
  2491                              <1> 	;      ((swp+6 - address of user structure)) 
  2492                              <1> 	;
  2493                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2494                              <1> 	;
  2495                              <1> 	; INPUTS ->
  2496                              <1> 	;    AL	- new process number (to be swapped in)	 
  2497                              <1> 	; OUTPUTS ->
  2498                              <1> 	;    none
  2499                              <1> 	;
  2500                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2501                              <1> 	;
  2502                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2503 00004527 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2504 00004529 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2505 0000452E BF[E4640000]        <1> 	mov	edi, user ; active user (u) structure	
  2506 00004533 F3A5                <1> 	rep	movsd
  2507 00004535 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2508 00004536 8B3D[E8640000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2509                              <1> 			     ;      points to user registers)
  2510 0000453C 8B0D[E4640000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2511                              <1> 			     ; (for IRET)
  2512                              <1> 			     ; [u.sp] -> EIP (user)
  2513                              <1> 			     ; [u.sp+4]-> CS (user)
  2514                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2515                              <1> 			     ; [u.sp+12] -> ESP (user)
  2516                              <1> 			     ; [u.sp+16] -> SS (user)		
  2517                              <1> 	; 28/08/2015
  2518 00004542 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2519 00004544 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2520                              <1> 			     ; (for IRET) 	
  2521 00004547 C1E902              <1> 	shr	ecx, 2	       		
  2522 0000454A F3A5                <1> 	rep	movsd
  2523 0000454C 8B25[E8640000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2524 00004552 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2525 00004553 C3                  <1> 	retn
  2526                              <1> 
  2527                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2528                              <1> 	;rswap:
  2529                              <1>        		; asl r1 / process number x2 for index
  2530                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2531                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2532                              <1>        		; bis $2000,swp / read
  2533                              <1>        		; jsr r0,ppoke / read it in 
  2534                              <1> 	; 1:
  2535                              <1>        		; tstb swp+1 / done
  2536                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2537                              <1>        		; mov u.emt,*$30 / yes move these
  2538                              <1>        		; mov u.ilgins,*$10 / back
  2539                              <1>        		; rts r0 / return
  2540                              <1> 
  2541                              <1> 	;unpack: ; / move stack back to its normal place
  2542                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2543                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2544                              <1> 		; blos 2f / yes, return
  2545                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2546                              <1> 			     ; / before swapping
  2547                              <1> 		; bhis 2f / yes, return
  2548                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2549                              <1> 		; add r3,r2
  2550                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2551                              <1> 	; 1:
  2552                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2553                              <1> 		; cmp r2,u.break / in core
  2554                              <1> 		; bne 1b
  2555                              <1> 	; 2:
  2556                              <1>        		; rts r0
  2557                              <1> 
  2558                              <1> putlu: 
  2559                              <1> 	; 12/09/2015
  2560                              <1> 	; 02/09/2015
  2561                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2562                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2563                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2564                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2565                              <1> 	; the last process on the queue to process in r1 by putting
  2566                              <1> 	; the process number in r1 into the last process's link.
  2567                              <1> 	;
  2568                              <1> 	; INPUTS ->
  2569                              <1> 	;    r1 - user process number
  2570                              <1> 	;    r2 - points to lowest priority queue 
  2571                              <1> 	;    p.dska - disk address of the process		
  2572                              <1> 	;    u.emt - determines handling of emt's 	
  2573                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2574                              <1> 	; OUTPUTS ->
  2575                              <1> 	;    r3 - process number of last process on the queue upon
  2576                              <1> 	;	  entering putlu
  2577                              <1> 	;    p.link-1 + r3 - process number in r1
  2578                              <1> 	;    r2 - points to lowest priority queue
  2579                              <1> 	;
  2580                              <1> 	; ((Modified registers: EDX, EBX)) 
  2581                              <1> 	;
  2582                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2583                              <1> 
  2584                              <1> 	; eBX = r2
  2585                              <1> 	; eAX = r1 (AL=r1b)
  2586                              <1> 
  2587 00004554 BB[DE640000]        <1> 	mov	ebx, runq
  2588 00004559 0FB613              <1> 	movzx  	edx, byte [ebx]
  2589 0000455C 43                  <1> 	inc	ebx
  2590 0000455D 20D2                <1> 	and	dl, dl
  2591                              <1> 		; tstb (r2)+ / is queue empty?
  2592 0000455F 740A                <1>        	jz	short putlu_1
  2593                              <1> 		; beq 1f / yes, branch
  2594 00004561 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2595                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2596                              <1> 			     ; / in r3
  2597 00004563 8882[53620000]      <1>        	mov	[edx+p.link-1], al
  2598                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2599                              <1> 			     ; / "last users" link
  2600 00004569 EB03                <1> 	jmp	short putlu_2
  2601                              <1> 		; br 2f /
  2602                              <1> putlu_1: ; 1:
  2603 0000456B 8843FF              <1> 	mov	[ebx-1], al
  2604                              <1>        		; movb r1,-1(r2) / user is only user; 
  2605                              <1> 			    ; / put process no. at beginning and at end
  2606                              <1> putlu_2: ; 2: 
  2607 0000456E 8803                <1> 	mov	[ebx], al
  2608                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2609                              <1> 			     ; / on the queue
  2610 00004570 88C2                <1> 	mov	dl, al
  2611 00004572 88B2[53620000]      <1>         mov     [edx+p.link-1], dh ; 0
  2612                              <1> 		; dec r2 / restore r2
  2613 00004578 C3                  <1>         retn
  2614                              <1> 		; rts r0
  2615                              <1> 
  2616                              <1> ;copyz:
  2617                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2618                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2619                              <1> ;       mov     (r0)+,r1
  2620                              <1> ;       mov     (r0)+,r2
  2621                              <1> ;1:
  2622                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2623                              <1> ;       cmp     r1,r2 
  2624                              <1> ;       blo     1b
  2625                              <1> ;       mov     (sp)+,r2 / restore r2
  2626                              <1> ;       mov     (sp)+,r1 / restore r1
  2627                              <1> ;       rts     r0 
  2628                              <1> 
  2629                              <1> idle:
  2630                              <1> 	; 01/09/2015
  2631                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2632                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2633                              <1> 	; (idle & wait loop)
  2634                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2635                              <1> 	; idle procedure!
  2636                              <1>       	;
  2637                              <1>   	; 01/09/2015
  2638 00004579 FB                  <1> 	sti
  2639                              <1>       	; 29/07/2013
  2640 0000457A F4                  <1>       	hlt
  2641 0000457B 90                  <1>       	nop ; 10/10/2013
  2642 0000457C 90                  <1>       	nop
  2643 0000457D 90                  <1>       	nop
  2644                              <1>       	; 23/10/2013
  2645 0000457E 90                  <1>       	nop
  2646 0000457F 90                  <1>       	nop
  2647 00004580 90                  <1>       	nop
  2648 00004581 90                  <1>       	nop
  2649 00004582 C3                  <1>       	retn      
  2650                              <1> 
  2651                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2652                              <1> 	;clr *$ps / clear ps
  2653                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2654                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2655                              <1> 	;1 / wait for interrupt
  2656                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2657                              <1> 	;mov (sp)+,*$ps
  2658                              <1> 	;rts r0
  2659                              <1> 
  2660                              <1> clear:
  2661                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2662                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2663                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2664                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2665                              <1> 	; on the current device (cdev)
  2666                              <1> 	;	
  2667                              <1> 	; INPUTS ->
  2668                              <1> 	;    r1 - block number of block to be zeroed
  2669                              <1> 	;    cdev - current device number 
  2670                              <1> 	; OUTPUTS ->
  2671                              <1> 	;    a zeroed I/O buffer onto the current device
  2672                              <1> 	;    r1 - points to last entry in the I/O buffer
  2673                              <1> 	;
  2674                              <1> 	; ((AX = R1)) input/output
  2675                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2676                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2677                              <1> 
  2678 00004583 E88E0E0000          <1> 	call 	wslot
  2679                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2680                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2681 00004588 89DF                <1> 	mov	edi, ebx ; r5
  2682 0000458A 89C2                <1> 	mov	edx, eax
  2683 0000458C B980000000          <1> 	mov	ecx, 128
  2684                              <1> 		; mov $256.,r3
  2685 00004591 31C0                <1> 	xor	eax, eax
  2686 00004593 F3AB                <1> 	rep	stosd
  2687 00004595 89D0                <1> 	mov	eax, edx
  2688                              <1> ; 1: 
  2689                              <1>        		; clr (r5)+ / zero data word in buffer
  2690                              <1>        		; dec r3
  2691                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2692                              <1> 	;call	dskwr
  2693                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2694                              <1>                              ; / block specified in r1
  2695                              <1> 	; eAX (r1) = block number
  2696                              <1> 	;retn
  2697                              <1> 		; rts r0
  2698                              <1> 	; 24/12/2021
  2699 00004597 E9870E0000          <1> 	jmp	dskwr
  2117                                  %include 'u4.s'        ; 15/04/2015
  2118                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2119                              <1> ; Last Modification: 26/02/2022
  2120                              <1> ; ----------------------------------------------------------------------------
  2121                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2122                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2123                              <1> ;
  2124                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2125                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2126                              <1> ; <Bell Laboratories (17/3/1972)>
  2127                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2128                              <1> ;
  2129                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2130                              <1> ;
  2131                              <1> ; ****************************************************************************
  2132                              <1> 
  2133                              <1> ;setisp:
  2134                              <1>        ;mov     r1,-(sp)
  2135                              <1>        ;mov     r2,-(sp)
  2136                              <1>        ;mov     r3,-(sp)
  2137                              <1>        ;mov     clockp,-(sp)
  2138                              <1>        ;mov     $s.syst+2,clockp
  2139                              <1>        ;jmp     (r0)
  2140                              <1> 
  2141                              <1> clock: ; / interrupt from 60 cycle clock
  2142                              <1> 	
  2143                              <1> 	; 14/10/2015
  2144                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2145                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2146                              <1> 
  2147                              <1>        ;mov     r0,-(sp) / save r0
  2148                              <1>        ;tst     *$lks / restart clock?
  2149                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2150                              <1>        ;inc     (r0)
  2151                              <1>        ;bne     1f
  2152                              <1>        ;inc     -(r0)
  2153                              <1> ;1:
  2154                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2155                              <1>        ;inc     (r0)
  2156                              <1>        ;bne     1f
  2157                              <1>        ;inc     -(r0)
  2158                              <1> ;1:
  2159                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2160                              <1> 
  2161 0000459C 803D[2E650000]00    <1> 	cmp	byte [u.quant], 0
  2162 000045A3 772C                <1> 	ja	short clk_1
  2163                              <1> 	;
  2164 000045A5 803D[E3640000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2165 000045AC 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2166 000045AE 803D[3B650000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2167 000045B5 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2168 000045B7 66833D[30650000]00  <1> 	cmp	word [u.intr], 0
  2169 000045BF 7616                <1> 	jna	short clk_2
  2170                              <1> clk_0:
  2171                              <1> 	; 14/10/2015
  2172 000045C1 FE05[E3640000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2173 000045C7 58                  <1> 	pop	eax ; return address to the timer interrupt
  2174                              <1> 	;
  2175 000045C8 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2176                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2177 000045CA E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2178                              <1> 	;
  2179 000045CC E97FEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2180                              <1> clk_1:
  2181 000045D1 FE0D[2E650000]      <1> 	dec	byte [u.quant]
  2182                              <1> clk_2:
  2183 000045D7 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2184                              <1> 
  2185                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2186                              <1> 
  2187                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2188                              <1>        ;decb    (r0)
  2189                              <1>        ;bge     1f / if less than 0
  2190                              <1>        ;clrb    (r0) / make it 0
  2191                              <1> ;1: / decrement time out counts return now if priority was not 0
  2192                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2193                              <1>        ;bge     2f / yes, check time outs
  2194                              <1>        ;tstb    (r0) / no, user timed out?
  2195                              <1>        ;bne     1f / no
  2196                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2197                              <1>        ;bne     1f / no, 1f
  2198                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2199                              <1>        ;sys     0 / sysrele
  2200                              <1>        ;rti
  2201                              <1> ;2: / priority is high so just decrement time out counts
  2202                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2203                              <1> ;2:
  2204                              <1>        ;tstb    (r0) / is the time out?
  2205                              <1>        ;beq     3f / yes, 3f (get next entry)
  2206                              <1>        ;decb    (r0) / no, decrement the time
  2207                              <1>        ;bne     3f / isit zero now?
  2208                              <1>        ;incb    (r0) / yes, increment the time
  2209                              <1> ;3:
  2210                              <1>        ;inc     r0 / next entry
  2211                              <1>        ;cmp     r0,$touts / end of toutt table?
  2212                              <1>        ;blo     2b / no, check this entry
  2213                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2214                              <1>        ;rti / return from interrupt
  2215                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2216                              <1>        ;mov     (sp)+,r0 / restore r0
  2217                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2218                              <1>        ;jsr     r0,setisp / save registers
  2219                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2220                              <1>                                ;  / the table
  2221                              <1> ;1:
  2222                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2223                              <1>        ;beq     2f / yes
  2224                              <1>        ;decb    toutt(r0) / no, decrement the time
  2225                              <1>        ;bne     2f / is the time 0, now
  2226                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2227                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2228                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2229                              <1> ;2:
  2230                              <1>        ;dec     r0 / set up r0 for next entry
  2231                              <1>        ;bge     1b / finished? , no, go back
  2232                              <1>        ;br      retisp / yes, restore registers and do a rti
  2233                              <1> 
  2234                              <1> ;retisp:
  2235                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2236                              <1>        ;mov     (sp)+,r3
  2237                              <1>        ;mov     (sp)+,r2
  2238                              <1>        ;mov     (sp)+,r1
  2239                              <1>        ;mov     (sp)+,r0
  2240                              <1>        ;rti     / return from interrupt
  2241                              <1> 
  2242                              <1> 
  2243                              <1> wakeup: ; / wakeup processes waiting for an event 
  2244                              <1> 	; / by linking them to the queue
  2245                              <1> 	;
  2246                              <1> 	; 26/02/2022
  2247                              <1> 	; 15/09/2015
  2248                              <1> 	; 29/06/2015
  2249                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2250                              <1> 	;
  2251                              <1> 	; 15/05/2013 - 02/06/2014
  2252                              <1> 	; Retro UNIX 8086 v1 modification !
  2253                              <1> 	; (Process/task switching routine by using
  2254                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2255                              <1> 	;
  2256                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2257                              <1> 	; sleeping in the specified wait channel by creating a link 
  2258                              <1> 	; to it from the last user process on the run queue.
  2259                              <1> 	; If there is no process to wake up, nothing happens.
  2260                              <1> 	;
  2261                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2262                              <1> 	; 'switching' status of the current process (owns current tty)
  2263                              <1> 	; (via alt + function keys) to a process which has highest
  2264                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2265                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2266                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2267                              <1> 	; tty for tty switching by keyboard.)	 
  2268                              <1> 	; 
  2269                              <1> 	; INPUT -> 
  2270                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2271                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2272                              <1> 	;
  2273                              <1> 	; ((modified registers: EAX, EBX))
  2274                              <1> 	;
  2275 000045D8 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2276 000045DB 81C3[88610000]      <1> 	add	ebx, wlist
  2277 000045E1 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2278 000045E3 20C0                <1> 	and	al, al
  2279 000045E5 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2280                              <1> 	;
  2281 000045E7 30E4                <1> 	xor	ah, ah
  2282 000045E9 8825[2E650000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2283 000045EF 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2284                              <1> 	; 15/09/2015
  2285 000045F1 0FB6D8              <1> 	movzx	ebx, al
  2286                              <1> 	; 26/02/2022 (p.waitc is not used)
  2287                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2288 000045F4 FEC4                <1> 	inc	ah
  2289 000045F6 88A3[63620000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2290                              <1> 	;
  2291 000045FC 57                  <1> 	push	edi
  2292 000045FD 52                  <1> 	push	edx
  2293 000045FE E851FFFFFF          <1> 	call	putlu
  2294 00004603 5A                  <1> 	pop	edx
  2295 00004604 5F                  <1> 	pop	edi
  2296                              <1> wa0:
  2297 00004605 C3                  <1> 	retn
  2298                              <1> 
  2299                              <1> sleep: 
  2300                              <1> 	; 26/02/2022
  2301                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2302                              <1> 	; 15/09/2015
  2303                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2304                              <1> 	;
  2305                              <1> 	; 09/05/2013 - 20/03/2014
  2306                              <1> 	;
  2307                              <1> 	; Retro UNIX 8086 v1 modification !
  2308                              <1> 	; (Process/task switching and quit routine by using
  2309                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2310                              <1> 	;
  2311                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2312                              <1> 	; tty and tape output or input becomes available
  2313                              <1> 	; and process is put on waiting channel and swapped out,
  2314                              <1> 	; then -when the tty or tape is ready to write or read-
  2315                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2316                              <1> 	;
  2317                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2318                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2319                              <1> 	; status of the current process also INT 1Ch will count down
  2320                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2321                              <1> 	; to tty buffer of the current process and kernel will get
  2322                              <1> 	; user input by using tty buffer of the current process
  2323                              <1> 	; (instead of standard INT 16h interrupt).
  2324                              <1> 	; TTY output will be redirected to related video page of text mode
  2325                              <1> 	; (INT 10h will be called with different video page depending
  2326                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2327                              <1> 	; pseudo screens.)
  2328                              <1> 	;
  2329                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2330                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2331                              <1> 	; characters/data on serial port(s).
  2332                              <1> 	;
  2333                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2334                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2335                              <1> 	; 
  2336                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2337                              <1> 	;
  2338                              <1> 	;; 05/10/2013
  2339                              <1>         ;10/12/2013
  2340                              <1> 	;cmp   byte [u.uno], 1
  2341                              <1>         ;ja    short sleep0
  2342                              <1> 	;retn
  2343                              <1> 
  2344                              <1> 	; 20/03/2014
  2345                              <1> 	;mov	bx, [runq]
  2346                              <1> 	;cmp	bl, bh
  2347                              <1> 	;jne	short sleep0	
  2348                              <1> 	; 25/02/2014
  2349                              <1> 	;cmp word ptr [runq], 0
  2350                              <1> 	;ja short sleep0	
  2351                              <1> 	;retn
  2352                              <1> sleep0:
  2353                              <1> 	;
  2354 00004606 E849000000          <1> 	call	isintr
  2355                              <1> 	;jnz	sysret
  2356                              <1> 		; / wait for event
  2357                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2358                              <1> 			      ; / or quit from user
  2359                              <1>                		; br 2f / something happened
  2360                              <1> 			      ; / yes, his interrupt so return
  2361                              <1>                      	      ;	/ to user
  2362                              <1> 	; 24/12/2021
  2363 0000460B 7405                <1> 	jz	short sleep_2
  2364                              <1> sleep_3:
  2365 0000460D E9D9EAFFFF          <1> 	jmp	sysret
  2366                              <1> sleep_2:
  2367                              <1> 	; 30/06/2015
  2368 00004612 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2369 00004615 81C3[88610000]      <1> 	add	ebx, wlist
  2370 0000461B 8A03                <1> 	mov	al, [ebx]
  2371 0000461D 20C0                <1> 	and	al, al
  2372 0000461F 7407                <1> 	jz	short sleep1
  2373 00004621 53                  <1> 	push	ebx
  2374 00004622 E82DFFFFFF          <1> 	call	putlu
  2375 00004627 5B                  <1> 	pop	ebx
  2376                              <1> sleep1:
  2377 00004628 A0[3B650000]        <1> 	mov	al, [u.uno]    
  2378 0000462D 8803                <1>   	mov	[ebx], al 	; put the process number
  2379                              <1> 				; in the wait channel
  2380                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2381                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2382                              <1> 				     ; / on the stack
  2383                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2384                              <1> 				     ; / to put to sleep in there
  2385                              <1>         ; 15/09/2015
  2386 0000462F 0FB6D8              <1> 	movzx	ebx, al
  2387 00004632 C683[63620000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2388                              <1> 	; 26/02/2022 (p.waitc is not used)
  2389                              <1> 	;inc	ah
  2390                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2391                              <1> 	;
  2392 00004639 66FF35[D3640000]    <1> 	push    word [cdev]
  2393                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2394 00004640 E842FEFFFF          <1> 	call	swap
  2395                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2396 00004645 668F05[D3640000]    <1>         pop     word [cdev]
  2397                              <1> 		; mov (sp)+,cdev / restore device
  2398 0000464C E803000000          <1> 	call	isintr
  2399                              <1> 	; 22/09/2013
  2400                              <1> 	;jnz	sysret         
  2401                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2402                              <1>                		; br 2f / yes, return to new user
  2403                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2404                              <1> 				; / originally on the wait channel
  2405                              <1>        		; beq 1f / if 0 branch
  2406                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2407                              <1>        		; mov $300,*$ps / processor priority = 6
  2408                              <1> 		; jsr r0,putlu / create link to old process number
  2409                              <1>        		; clr *$ps / clear the status; process priority = 0
  2410                              <1> 	; 24/12/2021
  2411 00004651 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2412                              <1>      ;1:
  2413 00004653 C3                  <1> 	retn
  2414                              <1> 		; rts r0 / return
  2415                              <1>      ;2:
  2416                              <1>         ;;jmp	sysret
  2417                              <1> 		; jmp sysret / return to user
  2418                              <1> 
  2419                              <1> isintr:
  2420                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2421                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2422                              <1> 	;
  2423                              <1> 	; 09/05/2013 - 30/05/2014
  2424                              <1> 	;
  2425                              <1> 	; Retro UNIX 8086 v1 modification !
  2426                              <1> 	; (Process/task switching and quit routine by using
  2427                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2428                              <1> 	;
  2429                              <1> 	; Retro UNIX 8086 v1 modification:
  2430                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2431                              <1> 	;  and there is a 'quit' request by user;
  2432                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2433                              <1> 	;  "nothing to do". (20/10/2013)
  2434                              <1> 	;
  2435                              <1> 	; 20/10/2013
  2436 00004654 66833D[1C650000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2437 0000465C 761F                <1> 	jna	short isintr2 ; retn
  2438                              <1> 	; 03/09/2013
  2439                              <1> 	; (nothing to do)
  2440                              <1> 	;retn
  2441                              <1> 	; 22/09/2013
  2442 0000465E 66833D[30650000]00  <1> 	cmp	word [u.intr], 0
  2443 00004666 7615                <1> 	jna	short isintr2 ; retn
  2444                              <1> 	; 30/05/2014
  2445                              <1> 	;push	ax
  2446                              <1> 	; 24/12/2021
  2447 00004668 50                  <1> 	push	eax
  2448 00004669 66A1[32650000]      <1> 	mov	ax, [u.quit]
  2449 0000466F 6609C0              <1> 	or	ax, ax ; 0 ?
  2450 00004672 7408                <1> 	jz	short isintr1 ; zf = 1
  2451 00004674 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2452 00004678 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2453                              <1> 	;xor	ax, ax ; zf = 1
  2454                              <1> 	; 24/12/2021
  2455 0000467A 31C0                <1> 	xor	eax, eax ; zf = 1
  2456                              <1> isintr1:
  2457                              <1> 	;pop	ax
  2458                              <1> 	; 24/12/2021
  2459 0000467C 58                  <1> 	pop	eax
  2460                              <1> isintr2: ; 22/09/2013
  2461                              <1> 	; zf=1 -> nothing to do
  2462 0000467D C3                  <1> 	retn
  2463                              <1> 
  2464                              <1> 	; UNIX v1 original 'isintr' routine... 
  2465                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2466                              <1>        	;mov     r2,-(sp) / save r2
  2467                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2468                              <1>         ;                 / typewriter
  2469                              <1>        	;beq     1f / if 0, do nothing except skip return
  2470                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2471                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2472                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2473                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2474                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2475                              <1>         ;              / of interrupts
  2476                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2477                              <1>      ;1:
  2478                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2479                              <1>      ;4:
  2480                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2481                              <1>        	;mov     (sp)+,r1
  2482                              <1>        	;rts     r0
  2483                              <1>      ;3: / interrupt char = quit (fs)
  2484                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2485                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2486                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2487                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2488                              <1>      ;1: / find process control tty entry in tty block
  2489                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2490                              <1>        	;beq     1f / block found go to 1f
  2491                              <1>        	;add     $8,r1 / look at next tty block
  2492                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2493                              <1>        	;blo     1b / no
  2494                              <1>        	;br      4b / no process control tty found so go to 4b
  2495                              <1>      ;1:
  2496                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2497                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2498                              <1>         ;                  / identifier
  2499                              <1>        	;inc     0f / increment
  2500                              <1>      ;1:
  2501                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2502                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2503                              <1>         ;             / being typed out after you hit the interrupt
  2504                              <1>         ;             / key
  2505                              <1>        	;br      1b
  2118                                  %include 'u5.s'        ; 03/06/2015
  2119                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2120                              <1> ; Last Modification: 22/04/2022
  2121                              <1> ; ----------------------------------------------------------------------------
  2122                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2123                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2124                              <1> ;
  2125                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2126                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2127                              <1> ; <Bell Laboratories (17/3/1972)>
  2128                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2129                              <1> ;
  2130                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2131                              <1> ;
  2132                              <1> ; ****************************************************************************
  2133                              <1> 
  2134                              <1> mget:
  2135                              <1> 	; 22/04/2022
  2136                              <1> 	; 09/01/2022
  2137                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2138                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2139                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2140                              <1> 	;
  2141                              <1> 	; Get existing or (allocate) a new disk block for file
  2142                              <1> 	; 
  2143                              <1> 	; INPUTS ->
  2144                              <1> 	;    u.fofp (file offset pointer)
  2145                              <1> 	;    inode 
  2146                              <1> 	;    u.off (file offset)
  2147                              <1> 	; OUTPUTS ->
  2148                              <1> 	;    r1 (physical block number)
  2149                              <1> 	;    r2, r3, r5 (internal)
  2150                              <1> 	;
  2151                              <1> 	; ((AX = R1)) output
  2152                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2153                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2154                              <1> 
  2155                              <1> 		; mov *u.fofp,mq / file offset in mq
  2156                              <1> 		; clr ac / later to be high sig
  2157                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2158                              <1> 		; mov mq,r2
  2159                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2160                              <1> 		; bne 4f / branch for large file
  2161                              <1> mget_0:	
  2162                              <1> 	; 09/01/2022
  2163 0000467E 29C0                <1> 	sub	eax, eax
  2164 00004680 29D2                <1> 	sub	edx, edx
  2165 00004682 29C9                <1> 	sub	ecx, ecx
  2166 00004684 29DB                <1> 	sub	ebx, ebx
  2167                              <1> 
  2168 00004686 8B35[FC640000]      <1>         mov     esi, [u.fofp]
  2169                              <1>         ;movzx	ebx, byte [esi+1]
  2170                              <1> 	; 09/01/2022
  2171 0000468C 46                  <1> 	inc	esi
  2172 0000468D 8A1E                <1> 	mov	bl, [esi]
  2173                              <1> 
  2174                              <1> 	; BX = r2
  2175                              <1>         ; 24/12/2021
  2176 0000468F F605[E5610000]10    <1> 	test	byte [i.flgs+1], 10h
  2177                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2178                              <1> 				  ; is this a large or small file
  2179 00004696 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2180                              <1> 
  2181 00004698 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2182                              <1> 		; bit $!17,r2
  2183 0000469B 7525                <1> 	jnz 	short mget_2
  2184                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2185 0000469D 80E30E              <1>         and     bl, 0Eh  
  2186                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2187                              <1> 	; 09/01/2021
  2188 000046A0 668B83[EA610000]    <1> 	mov	ax, [ebx+i.dskp]
  2189                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2190                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2191                              <1> 	; 24/12/2021
  2192 000046A7 09C0                <1> 	or	eax, eax
  2193                              <1> 	;or 	ax, ax
  2194 000046A9 7516                <1> 	jnz 	short mget_1 
  2195                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2196                              <1> 		       ; / for file
  2197 000046AB E8A6000000          <1> 	call 	alloc
  2198                              <1> 		; jsr r0,alloc / allocate a new block
  2199                              <1>          ; eAX (r1) = Physical block number
  2200 000046B0 668983[EA610000]    <1> 	mov 	[ebx+i.dskp], ax
  2201                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2202 000046B7 E835020000          <1> 	call 	setimod	
  2203                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2204 000046BC E8C2FEFFFF          <1> 	call	clear
  2205                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2206                              <1> mget_1: ; 2:
  2207                              <1>         ; eAX (r1) = Physical block number
  2208 000046C1 C3                  <1> 	retn 
  2209                              <1> 		; rts r0
  2210                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2211 000046C2 E88F000000          <1> 	call 	alloc
  2212                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2213                              <1> 	                     ; / block number in r1
  2214                              <1>         ; eAX (r1) = Physical block number
  2215 000046C7 E84A0D0000          <1> 	call 	wslot
  2216                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2217                              <1> 			     ; / first data word in buffer
  2218                              <1>         ; eAX (r1) = Physical block number
  2219                              <1> 	; 09/01/2022
  2220 000046CC 31C9                <1> 	xor	ecx, ecx
  2221 000046CE B108                <1> 	mov	cl, 8
  2222                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2223                              <1> 		   ; into new indirect block area for the new
  2224                              <1> 		   ; large file		
  2225 000046D0 89DF                <1> 	mov 	edi, ebx ; r5
  2226 000046D2 BE[EA610000]        <1> 	mov 	esi, i.dskp 
  2227                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2228                              <1> 			   ; / block pointers
  2229                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2230                              <1> 			  ; / large file
  2231                              <1> 	; 22/04/2022
  2232 000046D7 50                  <1> 	push	eax ; * ; bugfix
  2233                              <1> 
  2234                              <1> 	;xor 	ax, ax ; mov ax, 0
  2235                              <1> 	; 24/12/2021
  2236 000046D8 31C0                <1> 	xor	eax, eax
  2237                              <1> mget_3: ;1:
  2238 000046DA 66A5                <1> 	movsw
  2239                              <1> 		; mov (r2),(r5)+
  2240 000046DC 668946FE            <1> 	mov 	[esi-2], ax
  2241                              <1> 		; clr (r2)+
  2242 000046E0 E2F8                <1> 	loop	mget_3 ; 1b
  2243                              <1> 		; dec r3
  2244                              <1> 		; bgt 1b
  2245                              <1> 
  2246 000046E2 B1F8                <1> 	mov 	cl, 256-8
  2247                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2248                              <1> mget_4:	; 1
  2249 000046E4 F366AB              <1> 	rep 	stosw
  2250                              <1> 		; clr (r5)+
  2251                              <1> 		; dec r3
  2252                              <1> 		; bgt 1b
  2253                              <1> 
  2254                              <1> 	; 22/04/2022
  2255                              <1> 	;pop	eax ; * ; bugfix
  2256                              <1> 
  2257                              <1> 	; 24/03/2013
  2258                              <1>         ; AX (r1) = Physical block number
  2259 000046E7 E8370D0000          <1> 	call	dskwr
  2260                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2261                              <1> 
  2262                              <1> 	; 22/04/2022
  2263 000046EC 58                  <1> 	pop	eax ; * ; bugfix
  2264                              <1> 
  2265                              <1>         ; eAX (r1) = Physical block number
  2266 000046ED 66A3[EA610000]      <1> 	mov 	[i.dskp], ax
  2267                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2268                              <1> 	; 09/01/2022
  2269 000046F3 800D[E5610000]10    <1> 	or	byte [i.flgs+1], 10h
  2270                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2271                              <1> 		; bis $10000,i.flgs / set large file bit 
  2272                              <1> 				  ; / in i.flgs word of i-node
  2273 000046FA E8F2010000          <1> 	call	setimod
  2274                              <1> 		; jsr r0,setimod / set i-node modified flag
  2275 000046FF E97AFFFFFF          <1>         jmp     mget_0 
  2276                              <1> 		; br mget
  2277                              <1> 
  2278                              <1> mget_5:  ; 4 ; large file
  2279                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2280                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2281                              <1> 			    ; / in indirect block
  2282                              <1> 		; mov r2,-(sp) / save on stack (*)
  2283                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2284                              <1>        		          ; / indirect block
  2285                              <1> 		; bic $!16,r2
  2286 00004704 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2287 00004707 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2288                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2289                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2290                              <1> 	; There is always 1 indirect block for this file system
  2291                              <1> 	; 09/01/2022
  2292 00004708 66A1[EA610000]      <1> 	mov	ax, [i.dskp]
  2293                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2294                              <1> 		; mov i.dskp(r2),r1
  2295                              <1> 	; 09/01/2022
  2296 0000470E 09C0                <1> 	or	eax, eax
  2297                              <1> 	;or 	ax, ax ; R1
  2298 00004710 7515                <1> 	jnz 	short mget_6 ; 2f
  2299                              <1> 		; bne 2f / if no indirect block exists
  2300 00004712 E83F000000          <1> 	call 	alloc
  2301                              <1> 		; jsr r0,alloc / allocate a new block
  2302 00004717 66A3[EA610000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2303                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2304 0000471D E8CF010000          <1> 	call 	setimod
  2305                              <1> 		; jsr r0,setimod / set i-node modified byte
  2306                              <1> 	; eAX = new block number
  2307 00004722 E85CFEFFFF          <1> 	call 	clear
  2308                              <1> 		; jsr r0,clear / clear new block
  2309                              <1> mget_6: ;2
  2310                              <1> 	; 05/03/2013
  2311                              <1> 	; eAX = r1, physical block number (of indirect block)
  2312 00004727 E8860C0000          <1> 	call 	dskrd ; read indirect block
  2313                              <1> 		; jsr r0,dskrd / read in indirect block
  2314 0000472C 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2315                              <1> 		; mov (sp)+,r2 / get offset
  2316                              <1> 	; eAX = r1, physical block number (of indirect block)
  2317 0000472D 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2318                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2319                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2320 0000472E 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2321                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2322                              <1> 	                  ; / points to location of inter
  2323                              <1> 	; 09/01/2022
  2324 00004730 668B03              <1> 	mov	ax, [ebx]
  2325                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2326                              <1> 			      ; in file sought in R1 (AX)
  2327                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2328                              <1> 	               	    ; / sought in r1
  2329                              <1> 	; 09/01/2022
  2330 00004733 09C0                <1> 	or	eax, eax
  2331                              <1> 	;or 	ax, ax
  2332 00004735 751D                <1>         jnz 	short mget_7 ; 2f
  2333                              <1> 		; bne 2f / if no block exists 
  2334 00004737 E81A000000          <1> 	call 	alloc
  2335                              <1> 		; jsr r0,alloc / allocate a new block
  2336 0000473C 668903              <1> 	mov 	[ebx], ax ; R1
  2337                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2338                              <1> 	                    ; / indirect block
  2339 0000473F 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2340                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2341 00004740 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2342 00004741 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2343 00004742 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2344                              <1> 		; mov (r2),-(sp) / save block number of new block
  2345                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2346 00004744 E8CD0C0000          <1> 	call 	wslot
  2347                              <1> 		; jsr r0,wslot
  2348                              <1>         ; eAX (r1) = physical block number
  2349                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2350 00004749 E8D50C0000          <1> 	call 	dskwr
  2351                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2352                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2353                              <1> 			     ; / back out on disk
  2354 0000474E 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2355                              <1> 		; mov (sp),r1 / restore block number of new block	
  2356                              <1> 	; eAX (r1) = physical block number of new block
  2357 0000474F E82FFEFFFF          <1> 	call 	clear
  2358                              <1> 		; jsr r0,clear / clear new block	
  2359                              <1> mget_7: ; 2
  2360 00004754 5A                  <1> 	pop 	edx ; **
  2361                              <1> 		; tst (sp)+ / bump stack pointer
  2362                              <1> 	; eAX (r1) = Block number of new block
  2363 00004755 C3                  <1> 	retn
  2364                              <1> 		; rts r0
  2365                              <1> 
  2366                              <1> alloc:
  2367                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2368                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2369                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2370                              <1> 	;
  2371                              <1> 	; get a free block and 
  2372                              <1> 	; set the corresponding bit in the free storage map
  2373                              <1> 	; 
  2374                              <1> 	; INPUTS ->
  2375                              <1> 	;    cdev (current device)
  2376                              <1> 	;    r2 
  2377                              <1> 	;    r3
  2378                              <1> 	; OUTPUTS ->
  2379                              <1> 	;    r1 (physical block number of block assigned)
  2380                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2381                              <1> 	;
  2382                              <1> 	; ((AX = R1)) output
  2383                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2384                              <1>         ;    ((Modified registers: DX, CX))  
  2385                              <1> 
  2386                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2387                              <1> 		;mov r3,-(sp)
  2388                              <1> 	;push 	ecx
  2389 00004756 53                  <1> 	push 	ebx ; R2
  2390                              <1> 	;push 	edx ; R3
  2391 00004757 BB[BC750000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2392                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2393 0000475C 803D[D3640000]00    <1> 	cmp 	byte [cdev], 0
  2394                              <1> 		; tst cdev
  2395 00004763 7605                <1> 	jna	short alloc_1
  2396                              <1> 		; beq 1f / drum is device
  2397 00004765 BB[C4770000]        <1> 	mov	ebx, mount
  2398                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2399                              <1> 			      ; / free storage map
  2400                              <1> alloc_1: ; 1
  2401                              <1> 	; 09/01/2022
  2402                              <1> 	;sub	ecx, ecx
  2403                              <1> 	;sub	edx, edx
  2404                              <1> 	;sub	eax, eax
  2405                              <1> 
  2406 0000476A 668B0B              <1>         mov	cx, [ebx]
  2407                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2408                              <1> 			     ; / storage map
  2409                              <1> 	; 09/01/2022
  2410 0000476D C1E103              <1> 	shl	ecx, 3
  2411                              <1> 	;shl	cx, 3
  2412                              <1> 		; asl r1 / multiply r1 by eight gives 
  2413                              <1> 		; number of blocks in device
  2414                              <1> 		; asl r1
  2415                              <1> 		; asl r1
  2416                              <1> 	;;push	cx ;; 01/08/2013
  2417                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2418 00004770 31C0                <1> 	xor 	eax, eax ; 0
  2419                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2420                              <1> alloc_2: ; 1
  2421 00004772 43                  <1> 	inc 	ebx ; 18/8/2012
  2422 00004773 43                  <1> 	inc 	ebx ; 
  2423 00004774 668B13              <1> 	mov 	dx, [ebx]
  2424                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2425                              <1> 	; 09/01/2022
  2426 00004777 09D2                <1> 	or	edx, edx
  2427                              <1> 	;or 	dx, dx
  2428 00004779 750D                <1> 	jnz 	short alloc_3 ; 1f
  2429                              <1> 		; bne 1f / branch if any free blocks in this word	
  2430 0000477B 6683C010            <1> 	add 	ax, 16
  2431                              <1> 		; add $16.,r1
  2432                              <1> 	; 09/01/2022
  2433 0000477F 39C8                <1> 	cmp	eax, ecx
  2434                              <1> 	;cmp 	ax, cx    
  2435                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2436 00004781 72EF                <1> 	jb 	short alloc_2
  2437                              <1> 		; blo 1b
  2438                              <1> 	; 14/11/2015
  2439                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2440                              <1> 	;	because of a (DMA or another) r/w error, 
  2441                              <1> 	;	we will be here, at 'jmp panic' code address,
  2442                              <1> 	;	even if the (disk) file system space is not full !!!
  2443                              <1> 	;	(cx = 0)	
  2444                              <1> 	;
  2445 00004783 E905E2FFFF          <1> 	jmp     panic 
  2446                              <1> 		; jmp panic / found no free storage
  2447                              <1> alloc_3: ; 1
  2448                              <1> 	; 09/01/2022
  2449 00004788 D1EA                <1> 	shr	edx, 1
  2450                              <1> 	;shr	dx, 1
  2451                              <1> 		; asr r3 / find a free block
  2452 0000478A 7203                <1> 	jc	short alloc_4 ; 1f
  2453                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2454                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2455                              <1> 	; 09/01/2022
  2456 0000478C 40                  <1> 	inc	eax
  2457                              <1> 	;inc	ax
  2458                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2459 0000478D EBF9                <1> 	jmp 	short alloc_3
  2460                              <1> 		; br 1b
  2461                              <1> alloc_4: ; 1:
  2462                              <1> 	;; pop cx ;; 01/08/2013
  2463                              <1> 		; tst (sp)+ / bump sp
  2464                              <1> 	; 02/04/2013 
  2465 0000478F E829000000          <1> 	call	free3
  2466                              <1> 		; jsr r0,3f / have found a free block
  2467                              <1> 	; 21/8/2012
  2468 00004794 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2469 00004797 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2470                              <1> 		; bic r3,(r2) / set bit for this block 
  2471                              <1> 		            ; / i.e. assign block
  2472                              <1> 		; br 2f
  2473 0000479A EB09                <1> 	jmp 	short alloc_5
  2474                              <1> 
  2475                              <1> free:
  2476                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2477                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2478                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2479                              <1> 	;
  2480                              <1> 	; calculates byte address and bit position for given block number
  2481                              <1> 	; then sets the corresponding bit in the free storage map
  2482                              <1> 	; 
  2483                              <1> 	; INPUTS ->
  2484                              <1> 	;    r1 - block number for a block structured device
  2485                              <1> 	;    cdev - current device 
  2486                              <1> 	; OUTPUTS ->
  2487                              <1> 	;    free storage map is updated
  2488                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2489                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2490                              <1> 	;
  2491                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2492                              <1>         ;  ((Modified registers: DX, CX))  
  2493                              <1> 
  2494                              <1> 		;mov r2,-(sp) / save r2, r3
  2495                              <1> 		;mov r3,-(sp)
  2496                              <1> 	;push 	ecx
  2497 0000479C 53                  <1> 	push 	ebx ; R2
  2498                              <1> 	;push 	edx ; R3 
  2499                              <1> 
  2500 0000479D E81B000000          <1>         call    free3
  2501                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2502                              <1> 				 ; / in free storage map for block
  2503 000047A2 660913              <1> 	or 	[ebx], dx  
  2504                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2505                              <1> 			    ;  / indicates free block	
  2506                              <1> 	; 0 -> allocated, 1 -> free
  2507                              <1> 
  2508                              <1> alloc_5:
  2509                              <1> 	; 07/04/2013
  2510                              <1> free_1: ; 2:
  2511                              <1> 	;pop 	edx
  2512                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2513 000047A5 5B                  <1> 	pop	ebx
  2514                              <1> 		; mov (sp)+,r2
  2515                              <1> 	; pop	ecx
  2516 000047A6 803D[D3640000]00    <1> 	cmp 	byte [cdev], 0
  2517                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2518                              <1> 			 ; / cdev = 1, mountable device
  2519 000047AD 7707                <1> 	ja	short alloc_6 ; 1f
  2520                              <1> 		; bne 1f
  2521                              <1> 	;mov	byte [smod], 1
  2522 000047AF FE05[E1640000]      <1> 	inc 	byte [smod]
  2523                              <1> 		; incb smod / set super block modified for drum
  2524                              <1> 	; eAX (r1) = block number
  2525 000047B5 C3                  <1> 	retn
  2526                              <1> 		; rts r0
  2527                              <1> free_2:
  2528                              <1> alloc_6: ; 1:
  2529                              <1> 	;mov 	byte [mmod], 1
  2530 000047B6 FE05[E2640000]      <1> 	inc 	byte [mmod]
  2531                              <1> 		; incb	mmod 
  2532                              <1> 		  ; / set super block modified for mountable device
  2533                              <1> 	; eAX (r1) = block number
  2534 000047BC C3                  <1> 	retn	
  2535                              <1> 		; rts r0
  2536                              <1> free3:
  2537                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2538                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2539                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2540                              <1> 	;
  2541                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2542                              <1> 	; 
  2543                              <1> alloc_free_3: ; 3
  2544                              <1> 	;mov 	dx, 1
  2545                              <1> 	; 09/01/2022
  2546 000047BD 31D2                <1> 	xor	edx, edx
  2547 000047BF 42                  <1> 	inc	edx
  2548                              <1> 	; edx = 1
  2549 000047C0 88C1                <1> 	mov 	cl, al
  2550                              <1> 		; mov r1,r2 / block number, k, = 1		
  2551 000047C2 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2552                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2553 000047C5 7402                <1> 	jz 	short free4
  2554                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2555                              <1> 			       ; / (k) mod 8
  2556                              <1> 	;shl 	dx, cl
  2557                              <1> 	; 09/01/2022
  2558 000047C7 D3E2                <1> 	shl	edx, cl
  2559                              <1> free4:
  2560 000047C9 0FB7D8              <1> 	movzx 	ebx, ax
  2561                              <1> 		; mov r1,r2 / divide block number by 16
  2562                              <1> 	; 09/01/2022
  2563 000047CC C1EB04              <1> 	shr	ebx, 4
  2564                              <1> 	;shr 	bx, 4
  2565                              <1> 		; asr r2
  2566                              <1> 		; asr r2
  2567                              <1> 		; asr r2
  2568                              <1> 		; asr r2
  2569                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2570                              <1> 		       ; / bit for block is in lower half of word
  2571                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2572                              <1> 		        ; / storage map
  2573                              <1> alloc_free_4: ; 1
  2574                              <1> 	; 09/01/2022
  2575 000047CF D1E3                <1> 	shl	ebx, 1
  2576                              <1> 	;shl 	bx, 1
  2577                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2578 000047D1 81C3[BE750000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2579                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2580                              <1> 	    		        ; / with block bit in it 	
  2581 000047D7 803D[D3640000]00    <1> 	cmp	byte [cdev], 0
  2582                              <1> 		; tst cdev
  2583 000047DE 7606                <1> 	jna	short alloc_free_5
  2584                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2585 000047E0 81C308020000        <1> 	add	ebx, mount - systm
  2586                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2587                              <1> 				    ; / mountable device with bit of block to be
  2588                              <1> 				    ; / freed
  2589                              <1> alloc_free_5: ; 1 
  2590 000047E6 C3                  <1> 	retn
  2591                              <1> 		; rts r0 / return to 'free'
  2592                              <1> 	      ; 2
  2593                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2594                              <1> 	
  2595                              <1> iget:
  2596                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2597                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2598                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2599                              <1> 	;
  2600                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2601                              <1> 	;
  2602                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2603                              <1> 	; 
  2604                              <1> 	; INPUTS ->
  2605                              <1> 	;    ii - current i-number, rootdir
  2606                              <1> 	;    cdev - new i-node device
  2607                              <1> 	;    idev - current i-node device
  2608                              <1> 	;    imod - current i-node modified flag
  2609                              <1> 	;    mnti - cross device file i-number
  2610                              <1> 	;    r1 - i-numbe rof new i-node
  2611                              <1> 	;    mntd - mountable device number		
  2612                              <1> 	; 	 
  2613                              <1> 	; OUTPUTS ->
  2614                              <1> 	;    cdev, idev, imod, ii, r1
  2615                              <1> 	;
  2616                              <1> 	; ((AX = R1)) input/output
  2617                              <1> 	;
  2618                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2619                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2620                              <1> 
  2621 000047E7 8A15[D3640000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2622 000047ED 8A35[D2640000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2623                              <1> 	;
  2624 000047F3 663B05[D0640000]    <1> 	cmp 	ax, [ii]
  2625                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2626 000047FA 7504                <1> 	jne 	short iget_1
  2627                              <1> 		; bne 1f
  2628 000047FC 38F2                <1> 	cmp	dl, dh
  2629                              <1> 		; cmp idev,cdev
  2630                              <1> 			  ; / is device number of i-node = current device
  2631 000047FE 7472                <1>         je      short iget_5
  2632                              <1> 		; beq 2f
  2633                              <1> iget_1: ; 1:
  2634 00004800 30DB                <1> 	xor	bl, bl
  2635 00004802 381D[E0640000]      <1> 	cmp	[imod], bl ; 0	
  2636                              <1> 		; tstb imod / has i-node of current file
  2637                              <1> 			  ; / been modified i.e., imod set
  2638 00004808 7629                <1> 	jna	short iget_2
  2639                              <1> 		; beq 1f
  2640 0000480A 881D[E0640000]      <1> 	mov	[imod], bl ; 0
  2641                              <1> 		;  clrb	imod / if it has, 
  2642                              <1> 			   ; / we must write the new i-node out on disk
  2643                              <1> 	; 24/12/2021
  2644 00004810 50                  <1> 	push	eax ; *
  2645                              <1> 	;push	ax
  2646                              <1> 		; mov r1,-(sp)
  2647                              <1> 	;mov	dl, [cdev]
  2648 00004811 52                  <1> 	push	edx ; **
  2649                              <1> 	;push	dx
  2650                              <1> 		; mov cdev,-(sp)
  2651 00004812 66A1[D0640000]      <1> 	mov	ax, [ii]
  2652                              <1> 		; mov ii,r1
  2653                              <1> 	;mov	dh, [idev]
  2654 00004818 8835[D3640000]      <1> 	mov	[cdev], dh
  2655                              <1> 		; mov idev,cdev
  2656 0000481E FEC3                <1> 	inc	bl ; 1
  2657                              <1> 	; 31/07/2013
  2658 00004820 881D[70650000]      <1> 	mov     [rw], bl ; 1 == write 
  2659                              <1> 	;;28/07/2013 rw -> u.rw
  2660                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2661 00004826 E848000000          <1> 	call	icalc
  2662                              <1> 		; jsr r0,icalc; 1
  2663                              <1> 	;pop	dx
  2664                              <1> 	; 24/12/2021
  2665 0000482B 5A                  <1> 	pop	edx ; **
  2666 0000482C 8815[D3640000]      <1> 	mov	[cdev], dl
  2667                              <1> 		; mov (sp)+,cdev
  2668                              <1> 	; 24/12/2021
  2669 00004832 58                  <1> 	pop	eax ; *
  2670                              <1> 	;pop	ax
  2671                              <1> 		; mov (sp)+,r1
  2672                              <1> iget_2: ; 1:
  2673 00004833 6621C0              <1> 	and	ax, ax
  2674                              <1> 		; tst r1 / is new i-number non zero
  2675 00004836 7434                <1> 	jz	short iget_4 ; 2f
  2676                              <1> 		; beq 2f / branch if r1=0
  2677                              <1> 
  2678                              <1> 	;mov 	dl, [cdev]
  2679 00004838 08D2                <1> 	or	dl, dl
  2680                              <1> 		; tst cdev / is the current device number non zero
  2681                              <1> 			 ; / (i.e., device =/ drum)
  2682 0000483A 7517                <1> 	jnz	short iget_3 ;  1f
  2683                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2684 0000483C 663B05[D6640000]    <1> 	cmp	ax, [mnti]			
  2685                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2686                              <1> 			    ; / file (root directory of mounted device)
  2687 00004843 750E                <1> 	jne	short iget_3 ; 1f
  2688                              <1> 		; bne 1f
  2689                              <1>         ;mov    bl, [mntd]
  2690 00004845 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2691 00004847 8815[D3640000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2692                              <1> 		; mov mntd,cdev / make mounted device the current device
  2693 0000484D 66A1[DC640000]      <1> 	mov	ax, [rootdir]
  2694                              <1> 		; mov rootdir,r1
  2695                              <1> iget_3: ; 1:
  2696 00004853 66A3[D0640000]      <1> 	mov	[ii], ax
  2697                              <1> 		; mov r1,ii
  2698 00004859 8815[D2640000]      <1> 	mov	[idev], dl ; cdev
  2699                              <1> 		; mov cdev,idev
  2700 0000485F 30DB                <1> 	xor	bl, bl
  2701                              <1>         ; 31/07/2013
  2702 00004861 881D[70650000]      <1> 	mov     [rw], bl ; 0 == read 
  2703                              <1> 	;;28/07/2013 rw -> u.rw       
  2704                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2705 00004867 E807000000          <1> 	call	icalc
  2706                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2707                              <1> iget_4: ; 2:
  2708 0000486C 66A1[D0640000]      <1> 	mov	ax, [ii]
  2709                              <1> 		; mov ii,r1
  2710                              <1> iget_5:
  2711 00004872 C3                  <1> 	retn
  2712                              <1> 		; rts r0
  2713                              <1> 
  2714                              <1> icalc:
  2715                              <1> 	; 04/04/2022 (47->31)
  2716                              <1> 	;	(Inode Table/List Address modification)
  2717                              <1> 	; 09/01/2022
  2718                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2719                              <1> 	; 02/07/2015
  2720                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2721                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2722                              <1> 	;
  2723                              <1> 	; calculate physical block number from i-number then
  2724                              <1> 	; read or write that block
  2725                              <1> 	;
  2726                              <1> 	; 'icalc' is called from 'iget'
  2727                              <1> 	;
  2728                              <1> 	; for original unix v1:
  2729                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2730                              <1>        	; / (i+31.) mod 16. bytes from its start
  2731                              <1> 	;
  2732                              <1> 	; for retro unix 8086 v1:
  2733                              <1> 	;  i-node is located in block (i+47)/16 and
  2734                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2735                              <1> 	;
  2736                              <1> 	; INPUTS ->
  2737                              <1> 	;    r1 - i-number of i-node
  2738                              <1> 	; 	 
  2739                              <1> 	; OUTPUTS ->
  2740                              <1> 	;    inode r/w
  2741                              <1> 	;
  2742                              <1> 	; ((AX = R1)) input
  2743                              <1> 	;
  2744                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2745                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2746                              <1> 	;
  2747 00004873 0FB7D0              <1> 	movzx	edx, ax	
  2748                              <1> 	;add	dx, 47
  2749                              <1> 	; 04/04/2022
  2750 00004876 6683C21F            <1> 	add	dx, 31
  2751 0000487A 89D0                <1> 	mov	eax, edx
  2752                              <1> 	;;add	ax, 47	; add 47 to inode number
  2753                              <1> 	;add	ax, 31
  2754                              <1> 		; add $31.,r1 / add 31. to i-number
  2755 0000487C 50                  <1> 	push	eax
  2756                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2757                              <1> 	; 09/01/2022
  2758 0000487D C1E804              <1> 	shr	eax, 4
  2759                              <1> 	;shr 	ax, 4
  2760                              <1> 		; asr r1 / divide by 16.
  2761                              <1> 		; asr r1
  2762                              <1> 		; asr r1
  2763                              <1> 		; asr r1 / r1 contains block number of block
  2764                              <1> 		       ; / in which i-node exists
  2765 00004880 E82D0B0000          <1> 	call	dskrd
  2766                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2767                              <1> 	; 31/07/2013
  2768 00004885 803D[70650000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2769                              <1> 	;; 28/07/2013 rw -> u.rw
  2770                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2771                              <1> 		; tst (r0)
  2772 0000488C 7605                <1> 	jna	short icalc_1
  2773                              <1> 		; beq 1f / branch to wslot when argument
  2774                              <1> 		       ; / in icalc call = 1
  2775                              <1> 	; eAX = r1 = block number
  2776 0000488E E8830B0000          <1> 	call	wslot
  2777                              <1> 		; jsr r0,wslot / set up data buffer for write
  2778                              <1> 			     ; / (will be same buffer as dskrd got)
  2779                              <1> 	; eBX = r5 points to first word in data area for this block
  2780                              <1> icalc_1: ; 1:
  2781 00004893 5A                  <1> 	pop	edx 
  2782 00004894 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2783                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2784                              <1> 			      ; / gives (i+31.) mod 16
  2785 00004897 C1E205              <1> 	shl 	edx, 5
  2786                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2787 0000489A 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2788 0000489C 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2789                              <1>           	; eSI (r5) points to first word in i-node i.	
  2790                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2791                              <1> 			     ; / 32.*(i+31.)mod16
  2792                              <1> 		; mov $5,lsh / for i-node i.
  2793                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2794 0000489E BF[E4610000]        <1> 	mov	edi, inode
  2795                              <1> 		; mov $inode,r1 / inode is address of first word 
  2796                              <1> 			      ; / of current i-node
  2797                              <1> 	; 09/01/2022
  2798 000048A3 29C9                <1> 	sub	ecx, ecx
  2799 000048A5 B108                <1> 	mov	cl, 8 
  2800                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2801                              <1> 		; mov $16.,r3
  2802                              <1>        ; 31/07/2013
  2803 000048A7 382D[70650000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2804                              <1>        ;;28/07/2013 rw -> u.rw                 
  2805                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2806                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2807 000048AD 7609                <1> 	jna	short icalc_3
  2808                              <1> 		; beq 2f / r0 now contains proper return address 
  2809                              <1> 		       ; / for rts r0
  2810                              <1> icalc_2: ; 1:
  2811 000048AF 87F7                <1> 	xchg 	esi, edi
  2812                              <1> 	; overwrite old i-node (in buffer to be written)
  2813 000048B1 F3A5                <1> 	rep 	movsd
  2814                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2815                              <1> 		; dec r3
  2816                              <1> 		; bgt 1b
  2817                              <1> 	;call	dskwr
  2818                              <1> 		; jsr r0,dskwr / write inode out on device
  2819                              <1> 	;retn
  2820                              <1> 		; rts r0
  2821                              <1> 	; 24/12/2021
  2822 000048B3 E96B0B0000          <1> 	jmp	dskwr
  2823                              <1> 
  2824                              <1> icalc_3: ; 2:
  2825                              <1> 	; copy new i-node into inode area of (core) memory
  2826 000048B8 F3A5                <1> 	rep 	movsd
  2827                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2828                              <1> 		                ; / "inode" area of core
  2829                              <1> 		; dec r3
  2830                              <1> 		; bgt 2b
  2831 000048BA C3                  <1> 	retn
  2832                              <1> 		; rts r0
  2833                              <1> 
  2834                              <1> access:
  2835                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2836                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2837                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2838                              <1> 	;
  2839                              <1> 	; check whether user is owner of file or user has read or write
  2840                              <1> 	; permission (based on i.flgs).
  2841                              <1> 	;
  2842                              <1> 	; INPUTS ->
  2843                              <1> 	;    r1 - i-number of file
  2844                              <1> 	;    u.uid
  2845                              <1> 	; arg0 -> (owner flag mask)	 		
  2846                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2847                              <1> 	; OUTPUTS ->
  2848                              <1> 	;    inode (or jump to error)
  2849                              <1> 	;
  2850                              <1> 	; ((AX = R1)) input/output
  2851                              <1> 	;
  2852                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2853                              <1> 	
  2854                              <1> 	;push	dx  ; save flags (DL)
  2855                              <1> 	; 24/12/2021
  2856 000048BB 52                  <1> 	push	edx ; save flags (DL)
  2857 000048BC E826FFFFFF          <1> 	call	iget
  2858                              <1> 		; jsr r0,iget / read in i-node for current directory
  2859                              <1> 			    ; / (i-number passed in r1)
  2860 000048C1 8A0D[E4610000]      <1> 	mov	cl, [i.flgs]
  2861                              <1> 		; mov i.flgs,r2
  2862                              <1> 	; 24/12/2021
  2863 000048C7 5A                  <1> 	pop	edx ; restore flags (DL)
  2864                              <1> 	;pop	dx  ; restore flags (DL)
  2865 000048C8 8A35[38650000]      <1> 	mov	dh, [u.uid]
  2866 000048CE 3A35[E7610000]      <1> 	cmp	dh, [i.uid]
  2867                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2868 000048D4 7503                <1> 	jne	short access_1
  2869                              <1> 		; bne 1f / no, then branch
  2870 000048D6 C0E902              <1> 	shr	cl, 2
  2871                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2872                              <1> 		        ; / read/write bits
  2873                              <1> 		; asrb r2
  2874                              <1> access_1: ; 1:
  2875 000048D9 20D1                <1> 	and	cl, dl
  2876                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2877                              <1> 			     ; / in access call
  2878 000048DB 7513                <1> 	jnz	short access_2
  2879                              <1> 		; bne 1f
  2880 000048DD 08F6                <1> 	or	dh, dh	; super user (root) ?
  2881                              <1> 		; tstb u.uid
  2882 000048DF 740F                <1> 	jz	short access_2 ; yes, super user
  2883                              <1> 	;jnz	error
  2884                              <1> 		; beq 1f
  2885                              <1> 		; jmp error
  2886 000048E1 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2886 000048E9 0000                <1>
  2887                              <1> 			; 'permission denied !' error
  2888 000048EB E9DBE7FFFF          <1> 	jmp	error
  2889                              <1> 
  2890                              <1> access_2: ; 1:
  2891                              <1> 	; DL = flags
  2892 000048F0 C3                  <1> 	retn
  2893                              <1> 		; rts r0
  2894                              <1> 
  2895                              <1> setimod:
  2896                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2897                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2898                              <1> 	;
  2899                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2900                              <1> 	; the inode has been modified. Also puts the time of modification
  2901                              <1> 	; into the inode.
  2902                              <1> 	;
  2903                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2904                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2905                              <1> 	;
  2906                              <1> 	
  2907                              <1> 	;push 	edx
  2908 000048F1 50                  <1> 	push	eax
  2909                              <1> 
  2910 000048F2 C605[E0640000]01    <1> 	mov 	byte [imod], 1
  2911                              <1> 		; movb $1,imod / set current i-node modified bytes
  2912                              <1> 	; Erdogan Tan 14-7-2012
  2913 000048F9 E81EE3FFFF          <1> 	call 	epoch
  2914                              <1> 		 ; mov s.time,i.mtim 
  2915                              <1> 			    ; / put present time into file modified time
  2916                              <1> 		 ; mov s.time+2,i.mtim+2
  2917                              <1> 
  2918 000048FE A3[FE610000]        <1> 	mov 	[i.mtim], eax
  2919                              <1> 	
  2920                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2921                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2922 00004903 833D[FA610000]00    <1> 	cmp	dword [i.ctim], 0
  2923 0000490A 7505                <1> 	jnz	short setimod_ok
  2924                              <1> 
  2925 0000490C A3[FA610000]        <1> 	mov 	[i.ctim], eax
  2926                              <1> 
  2927                              <1> setimod_ok: ; 31/07/2013
  2928 00004911 58                  <1> 	pop	eax
  2929                              <1> 	;pop	edx
  2930                              <1> 	
  2931 00004912 C3                  <1> 	retn
  2932                              <1> 		; rts r0
  2933                              <1> 
  2934                              <1> itrunc:
  2935                              <1> 	; 03/02/2022
  2936                              <1> 	; 09/01/2022
  2937                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2938                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2939                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2940                              <1> 	;
  2941                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2942                              <1> 	;  to zero length.
  2943                              <1> 	;
  2944                              <1> 	; INPUTS ->
  2945                              <1> 	;    r1 - i-number of i-node
  2946                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2947                              <1> 	;    i.flgs - large file flag		
  2948                              <1> 	;    i.size - size of file	
  2949                              <1> 	; 	 
  2950                              <1> 	; OUTPUTS ->
  2951                              <1> 	;    i.flgs - large file flag is cleared
  2952                              <1> 	;    i.size - set to 0	
  2953                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2954                              <1> 	;    setimod - set to indicate i-node has been modified
  2955                              <1> 	;    r1 - i-number of i-node  					
  2956                              <1> 	;
  2957                              <1> 	; ((AX = R1)) input/output
  2958                              <1> 	;
  2959                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2960                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2961                              <1> 
  2962 00004913 E8CFFEFFFF          <1> 	call	iget
  2963                              <1> 		; jsr r0,iget
  2964 00004918 BE[EA610000]        <1> 	mov	esi, i.dskp
  2965                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2966 0000491D 31C0                <1> 	xor	eax, eax
  2967                              <1> itrunc_1: ; 1:
  2968 0000491F 66AD                <1> 	lodsw
  2969                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2970                              <1> 	; 09/01/2022
  2971 00004921 09C0                <1> 	or	eax, eax
  2972                              <1> 	;or 	ax, ax
  2973 00004923 7433                <1> 	jz	short itrunc_5
  2974                              <1> 		; beq 5f
  2975 00004925 56                  <1> 	push	esi
  2976                              <1> 		; mov r2,-(sp)
  2977                              <1> 	; 09/01/2022
  2978 00004926 F605[E5610000]10    <1> 	test	byte [i.flgs+1], 10h
  2979                              <1> 	;test	word [i.flgs], 1000h
  2980                              <1> 		; bit $10000,i.flgs / test large file bit?
  2981 0000492D 7423                <1> 	jz	short itrunc_4
  2982                              <1> 		; beq 4f / if clear, branch
  2983 0000492F 50                  <1> 	push	eax
  2984                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2985 00004930 E87D0A0000          <1> 	call	dskrd
  2986                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2987                              <1> 			     ; / pointed to by r5
  2988                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2989                              <1> 	; 09/01/2022
  2990 00004935 31C9                <1> 	xor	ecx, ecx
  2991 00004937 FEC5                <1> 	inc	ch ; mov ch, 1
  2992                              <1> 	; ecx = 256
  2993                              <1> 	;mov	ecx, 256
  2994                              <1> 		; mov $256.,r3 / move word count into r3
  2995 00004939 89DE                <1> 	mov	esi, ebx
  2996                              <1> itrunc_2: ; 2:
  2997 0000493B 66AD                <1> 	lodsw
  2998                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2999                              <1> 			     ; / physical block number
  3000                              <1> 	; 09/01/2022
  3001 0000493D 21C0                <1> 	and	eax, eax
  3002                              <1> 	;and	ax, ax
  3003 0000493F 7407                <1> 	jz	short itrunc_3
  3004                              <1> 		; beq 3f / branch if zero
  3005                              <1> 	; 24/12/2021
  3006 00004941 51                  <1> 	push	ecx
  3007                              <1> 	;push	cx
  3008                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3009                              <1> 	;push	esi
  3010                              <1> 		; mov r5,-(sp)
  3011 00004942 E855FEFFFF          <1> 	call	free
  3012                              <1> 		; jsr r0,free / free block in free storage map
  3013                              <1> 	;pop	esi
  3014                              <1> 		; mov(sp)+,r5
  3015                              <1> 	;pop	cx
  3016 00004947 59                  <1> 	pop	ecx
  3017                              <1> 		; mov (sp)+,r3
  3018                              <1> itrunc_3: ; 3:
  3019 00004948 E2F1                <1> 	loop	itrunc_2
  3020                              <1> 		; dec r3 / decrement word count
  3021                              <1> 		; bgt 2b / branch if positive
  3022 0000494A 58                  <1> 	pop	eax
  3023                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3024                              <1> 			     ; / indirect block
  3025                              <1> 	; 01/08/2013
  3026                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3027                              <1> 	; 03/02/2022
  3028 0000494B 8025[E5610000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  3029                              <1> itrunc_4: ; 4:
  3030 00004952 E845FEFFFF          <1> 	call	free
  3031                              <1> 		; jsr r0,free / free indirect block
  3032 00004957 5E                  <1> 	pop	esi
  3033                              <1> 		; mov (sp)+,r2
  3034                              <1> itrunc_5: ; 5:
  3035 00004958 81FE[FA610000]      <1> 	cmp	esi, i.dskp+16
  3036                              <1> 		; cmp r2,$i.dskp+16.
  3037 0000495E 72BF                <1> 	jb	short itrunc_1	
  3038                              <1> 		; bne 1b / branch until all i.dskp entries check
  3039                              <1> 	; 03/02/2022
  3040                              <1> 	;and	byte [i.flgs+1], 0EFh
  3041                              <1> 	; 01/08/2013
  3042                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3043                              <1> 		; bic $10000,i.flgs / clear large file bit
  3044 00004960 BF[EA610000]        <1> 	mov	edi, i.dskp
  3045                              <1> 	;mov	cx, 8
  3046                              <1> 	;xor 	ax, ax
  3047                              <1> 	; 09/01/2022
  3048 00004965 29C9                <1> 	sub	ecx, ecx
  3049 00004967 B108                <1> 	mov	cl, 8
  3050 00004969 29C0                <1> 	sub	eax, eax
  3051 0000496B 66A3[E8610000]      <1> 	mov	[i.size], ax ; 0
  3052                              <1> 		; clr i.size / zero file size
  3053 00004971 F366AB              <1> 	rep	stosw
  3054                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3055                              <1> 			   ; / zero block pointers
  3056 00004974 E878FFFFFF          <1> 	call	setimod
  3057                              <1> 		; jsr r0,setimod / set i-node modified flag
  3058 00004979 66A1[D0640000]      <1> 	mov	ax, [ii]
  3059                              <1> 		; mov ii,r1
  3060 0000497F C3                  <1> 	retn
  3061                              <1> 		; rts r0
  3062                              <1> 
  3063                              <1> imap:
  3064                              <1> 	; 11/02/2022
  3065                              <1> 	; 03/02/2022
  3066                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3067                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3068                              <1> 	;
  3069                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3070                              <1> 	; allocation bit for an i-node whose number in r1.
  3071                              <1> 	;
  3072                              <1> 	; INPUTS ->
  3073                              <1> 	;    r1 - contains an i-number
  3074                              <1> 	;    fsp - start of table containing open files
  3075                              <1> 	;
  3076                              <1> 	; OUTPUTS ->
  3077                              <1> 	;    r2 - byte address of byte with the allocation bit
  3078                              <1> 	;    mq - a mask to locate the bit position.	
  3079                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3080                              <1> 	;
  3081                              <1> 	; ((AX = R1)) input/output
  3082                              <1> 	; ((DL/DX = MQ)) output
  3083                              <1> 	; ((BX = R2)) output
  3084                              <1> 	;
  3085                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3086                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3087                              <1> 	;
  3088                              <1> 		; / get the byte that has the allocation bit for 
  3089                              <1> 		; / the i-number contained in r1
  3090                              <1> 	;mov	dx, 1
  3091 00004980 B201                <1> 	mov	dl, 1
  3092                              <1> 		; mov $1,mq / put 1 in the mq
  3093 00004982 0FB7D8              <1> 	movzx	ebx, ax
  3094                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3095                              <1>  		          ; / in the map we must find
  3096 00004985 6683EB29            <1> 	sub	bx, 41
  3097                              <1> 		; sub $41.,r2 / r2 has i-41
  3098 00004989 88D9                <1> 	mov	cl, bl
  3099                              <1> 		; mov r2,r3 / r3 has i-41
  3100 0000498B 80E107              <1> 	and	cl, 7
  3101                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3102                              <1> 			   ; / the bit position
  3103 0000498E 7402                <1> 	jz	short imap1
  3104                              <1> 	;shl	dx, cl
  3105 00004990 D2E2                <1> 	shl	dl, cl
  3106                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3107                              <1> imap1:			   ; / to the left to mask the correct bit
  3108                              <1> 	; 03/02/2022
  3109 00004992 C1EB03              <1> 	shr	ebx, 3
  3110                              <1> 	;shr	bx, 3
  3111                              <1> 		; asr r2
  3112                              <1> 		; asr r2
  3113                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3114                              <1> 		       ; / from the start of the map
  3115                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3116 00004995 BE[BC750000]        <1> 	mov	esi, systm
  3117                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3118                              <1> 				; / the super block for drum
  3119                              <1> 	;cmp	word [cdev], 0
  3120 0000499A 803D[D3640000]00    <1> 	cmp	byte [cdev], 0
  3121                              <1> 		; tst cdev / is the device the disk
  3122 000049A1 7606                <1> 	jna	short imap2
  3123                              <1> 		; beq 1f / yes
  3124 000049A3 81C608020000        <1> 	add	esi, mount - systm
  3125                              <1> 		; add $mount-systm,r2 / for mounted device,
  3126                              <1> 			; / r2 points to 1st word of its super block
  3127                              <1> imap2: ; 1:
  3128 000049A9 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3129                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3130 000049AC 6683C304            <1> 	add	bx, 4
  3131 000049B0 01F3                <1> 	add	ebx, esi
  3132                              <1>         	; add (sp)+,r2 / ?
  3133                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3134                              <1> 		      ;; (2 + free map size + 2)
  3135                              <1> 		; add $2,r2 / ?
  3136                              <1> 
  3137                              <1> 	; 11/02/2022
  3138 000049B2 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3139 000049B8 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3140                              <1> 			  ; if inode num overs inode count
  3141                              <1> 
  3142                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3143                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3144                              <1> 
  3145                              <1> 	; 11/02/2022
  3146                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3147                              <1> 	;	(number of requested inode > inode count)
  3148                              <1> 
  3149 000049BA C3                  <1> 	retn
  3150                              <1> 		; rts r0
  2119                                  %include 'u6.s'        ; 31/05/2015
  2120                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS6.INC
  2121                              <1> ; Last Modification: 19/07/2022
  2122                              <1> ; ----------------------------------------------------------------------------
  2123                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2124                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2125                              <1> ;
  2126                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2127                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2128                              <1> ; <Bell Laboratories (17/3/1972)>
  2129                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2130                              <1> ;
  2131                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2132                              <1> ;
  2133                              <1> ; ****************************************************************************
  2134                              <1> 
  2135                              <1> readi:
  2136                              <1> 	; 11/01/2022
  2137                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2138                              <1> 	; 20/05/2015
  2139                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2140                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2141                              <1> 	;
  2142                              <1> 	; Reads from an inode whose number in R1
  2143                              <1> 	; 
  2144                              <1> 	; INPUTS ->
  2145                              <1> 	;    r1 - inode number
  2146                              <1> 	;    u.count - byte count user desires
  2147                              <1> 	;    u.base - points to user buffer
  2148                              <1> 	;    u.fofp - points to word with current file offset
  2149                              <1> 	; OUTPUTS ->
  2150                              <1> 	;    u.count - cleared
  2151                              <1> 	;    u.nread - accumulates total bytes passed back
  2152                              <1> 	;
  2153                              <1> 	; ((AX = R1)) input/output
  2154                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2155                              <1>         ;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -15/07/2022- 
  2156                              <1> 
  2157 000049BB 31D2                <1> 	xor	edx, edx ; 0
  2158 000049BD 8915[14650000]      <1> 	mov 	[u.nread], edx ; 0
  2159                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2160 000049C3 668915[51650000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2161 000049CA 3915[10650000]      <1> 	cmp 	[u.count], edx ; 0
  2162                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2163 000049D0 7701                <1> 	ja 	short readi_1 ; 1f
  2164                              <1> 		 ; bgt 1f / yes, branch
  2165 000049D2 C3                  <1> 	retn
  2166                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2167                              <1> readi_1: ; 1:
  2168                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2169 000049D3 6683F828            <1> 	cmp	ax, 40
  2170                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2171                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2172                              <1>         ;ja	dskr 
  2173                              <1> 		 ; ble 1f / yes, branch
  2174                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2175                              <1> 		 ;         / read file with i-node number (r1)
  2176                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2177                              <1> 	; 24/12/2021
  2178 000049D7 7605                <1> 	jna	short readi_3
  2179 000049D9 E9CF000000          <1> 	jmp	dskr
  2180                              <1> readi_3:
  2181                              <1> 	; (20/05/2015)
  2182 000049DE 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2183                              <1> 	; 1:
  2184 000049DF 0FB6D8              <1> 	movzx	ebx, al
  2185                              <1> 	; 11/01/2022
  2186 000049E2 C1E302              <1> 	shl	ebx, 2
  2187                              <1> 	;shl	bx, 2
  2188                              <1> 		 ; asl r1 / multiply inode number by 2
  2189 000049E5 81C3[E9490000]      <1> 	add	ebx, readi_2 - 4
  2190 000049EB FF23                <1> 	jmp	dword [ebx]	
  2191                              <1> 		 ; jmp *1f-2(r1)
  2192                              <1> readi_2: ; 1:
  2193 000049ED [394A0000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2194                              <1> 		 ;rtty / tty; r1=2
  2195                              <1> 		 ;rppt / ppt; r1=4
  2196 000049F1 [894A0000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2197                              <1> 		 ;rmem / mem; r1=6
  2198                              <1> 		 ;rrf0 / rf0
  2199                              <1> 		 ;rrk0 / rk0
  2200                              <1> 		 ;rtap / tap0
  2201                              <1> 		 ;rtap / tap1
  2202                              <1> 		 ;rtap / tap2
  2203                              <1> 		 ;rtap / tap3
  2204                              <1> 		 ;rtap / tap4
  2205                              <1> 		 ;rtap / tap5
  2206                              <1> 		 ;rtap / tap6
  2207                              <1> 		 ;rtap / tap7
  2208 000049F5 [73520000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2209 000049F9 [73520000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2210 000049FD [73520000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2211 00004A01 [73520000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2212 00004A05 [73520000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2213 00004A09 [73520000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2214 00004A0D [9E4A0000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2215 00004A11 [854A0000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2216                              <1> 		 ;rcvt / tty0
  2217 00004A15 [854A0000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2218                              <1> 		 ;rcvt / tty1
  2219 00004A19 [854A0000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2220                              <1> 		 ;rcvt / tty2
  2221 00004A1D [854A0000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2222                              <1> 		 ;rcvt / tty3
  2223 00004A21 [854A0000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2224                              <1> 		 ;rcvt / tty4
  2225 00004A25 [854A0000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2226                              <1> 		 ;rcvt / tty5
  2227 00004A29 [854A0000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2228                              <1> 		 ;rcvt / tty6
  2229 00004A2D [854A0000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2230                              <1> 		 ;rcvt / tty7
  2231 00004A31 [854A0000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2232                              <1> 		 ;rcrd / crd
  2233 00004A35 [854A0000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2234                              <1> 
  2235                              <1> rtty: ; / read from console tty
  2236                              <1> 	; 11/01/2022
  2237                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2238                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2239                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2240                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2241                              <1> 	;	     must be written immediate on video page (screen)
  2242                              <1> 	;	     when it is required.	
  2243                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2244                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2245                              <1> 	;
  2246                              <1> 	; Console tty buffer is PC keyboard buffer
  2247                              <1> 	; and keyboard-keystroke handling is different than original
  2248                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2249                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2250                              <1> 	;
  2251                              <1> 	; 06/12/2013
  2252 00004A39 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2253 00004A40 8A83[43620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2254                              <1> rttys:
  2255                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2256                              <1> 	               ; / of the control and status block
  2257                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2258                              <1> 		       ; / tty buffer
  2259                              <1> 	; 28/07/2013
  2260 00004A46 A2[40650000]        <1> 	mov 	[u.ttyn], al
  2261                              <1> 	; 13/01/2014
  2262 00004A4B FEC0                <1> 	inc	al
  2263 00004A4D A2[1C650000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2264                              <1> rtty_nc: ; 01/02/2014
  2265                              <1> 	; 29/09/2013
  2266                              <1> 	;mov	ecx, 10
  2267                              <1> 	; 11/01/2022
  2268 00004A52 29C9                <1> 	sub	ecx, ecx
  2269 00004A54 B10A                <1> 	mov	cl, 10
  2270                              <1> rtty_1: 	; 01/02/2014
  2271                              <1> 	;push 	cx ; 29/09/2013
  2272                              <1> 	; 24/12/2021
  2273 00004A56 51                  <1> 	push	ecx
  2274                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2275 00004A57 B001                <1> 	mov 	al, 1
  2276 00004A59 E8200B0000          <1> 	call 	getc
  2277                              <1> 	; 24/12/2021
  2278 00004A5E 59                  <1> 	pop	ecx
  2279                              <1> 	;pop 	cx ; 29/09/2013	
  2280 00004A5F 7516                <1> 	jnz	short rtty_2
  2281                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2282                              <1> 	               ; / of chars. Is this number non-zero?
  2283 00004A61 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2284                              <1> 	; 05/10/2013
  2285 00004A63 8A25[40650000]      <1> 	mov	ah, [u.ttyn]
  2286                              <1> 	; 29/09/2013
  2287 00004A69 E898FBFFFF          <1> 	call	sleep
  2288                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2289                              <1>                 ;           / (120 chars.)
  2290                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2291 00004A6E EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2292                              <1> 
  2293                              <1> rtty_idle:
  2294                              <1> 	; 29/07/2013
  2295 00004A70 E804FBFFFF          <1> 	call 	idle
  2296 00004A75 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2297                              <1> 	;1:
  2298                              <1> 		; tst 2(r5) / is the number of characters zero
  2299                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2300                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2301                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2302                              <1> 		          ; / contains the next char.
  2303                              <1> 		; dec 2(r5) / decrement the character count
  2304                              <1> rtty_2:
  2305 00004A77 30C0                <1> 	xor 	al, al
  2306 00004A79 E8000B0000          <1> 	call 	getc
  2307 00004A7E E896000000          <1> 	call	passc
  2308                              <1> 		; jsr r0,passc / move the character to core (user)
  2309                              <1> 	;; 17/10/2015 - 16/07/2015
  2310                              <1> 	; 19/06/2014
  2311                              <1> 	;;jnz	short rtty_nc
  2312 00004A83 58                  <1> 	pop	eax  ; (20/05/2015)
  2313 00004A84 C3                  <1> 	retn 
  2314                              <1> ;ret1:
  2315                              <1> 		; jmp ret / return to caller via 'ret'
  2316                              <1> 
  2317                              <1> rcvt:   ; < receive/read character from tty >
  2318                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2319                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2320                              <1> 	;
  2321                              <1> 	; Retro UNIX 8086 v1 modification !
  2322                              <1> 	; 
  2323                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2324                              <1> 	;		(exactly different than this one)
  2325                              <1> 	;	was in 'u9.s' file.
  2326                              <1> 	;
  2327 00004A85 2C0A                <1> 	sub 	al, 10
  2328                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2329                              <1> 	; 16/07/2013
  2330                              <1> 	; 21/05/2013
  2331 00004A87 EBBD                <1>         jmp     short rttys
  2332                              <1>       
  2333                              <1> ;rppt: / read paper tape
  2334                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2335                              <1> ;			 / places
  2336                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2337                              <1> ;		       / also enables read bit in prs
  2338                              <1> ;	jsr	r0,passc / place character in users buffer area
  2339                              <1> ;	br	rppt
  2340                              <1> 
  2341                              <1> rmem: ; / transfer characters from memory to a user area of core
  2342                              <1> 	; 17/10/2015
  2343                              <1> 	; 11/06/2015
  2344                              <1> 	; 24/05/2015
  2345                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2346                              <1> 	;
  2347 00004A89 8B35[FC640000]      <1> 	mov     esi, [u.fofp]
  2348                              <1> rmem_1:
  2349 00004A8F 8B1E                <1>         mov     ebx, [esi]        
  2350                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2351                              <1> 		               ; / to be transferred to user
  2352 00004A91 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2353                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2354                              <1> 			    ; / char in memory file
  2355 00004A93 8A03                <1> 	mov	al, [ebx]
  2356                              <1> 		; movb (r1),r1 / get character from memory file, 
  2357                              <1> 		             ; / put it in r1
  2358 00004A95 E87F000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2359                              <1> 			     ;  / the next byte of the users core area
  2360                              <1> 		; br rmem / continue
  2361 00004A9A 75F3                <1> 	jnz	short rmem_1
  2362                              <1> ret_:
  2363 00004A9C 58                  <1> 	pop	eax ; 09/06/2015
  2364 00004A9D C3                  <1> 	retn
  2365                              <1> 
  2366                              <1> rlpr:
  2367                              <1> ;1:
  2368                              <1> ;rcrd:
  2369 00004A9E C705[41650000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2369 00004AA6 0000                <1>
  2370 00004AA8 E91EE6FFFF          <1> 	jmp	error
  2371                              <1> 		;jmp	error / see 'error' routine
  2372                              <1> 
  2373                              <1> dskr:
  2374                              <1> 	; 19/07/2022
  2375                              <1> 	; 12/10/2015
  2376                              <1> 	; 21/08/2015
  2377                              <1> 	; 25/07/2015
  2378                              <1> 	; 10/07/2015
  2379                              <1> 	; 16/06/2015
  2380                              <1> 	; 31/05/2015
  2381                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2382                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2383                              <1> dskr_0:
  2384 00004AAD 50                  <1> 	push	eax
  2385                              <1> 		; mov (sp),r1 / i-number in r1
  2386                              <1> 	; AX = i-number
  2387 00004AAE E834FDFFFF          <1> 	call	iget
  2388                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2389 00004AB3 0FB715[E8610000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2390                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2391 00004ABA 8B1D[FC640000]      <1> 	mov	ebx, [u.fofp]
  2392 00004AC0 2B13                <1> 	sub	edx, [ebx]
  2393                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2394                              <1>         ; 12/10/2015
  2395                              <1> 	; jna     short ret_ 
  2396                              <1> 		; blos ret
  2397 00004AC2 7709                <1> 	ja	short dskr_1
  2398                              <1> 	;
  2399                              <1> dskr_retn: ; 12/10/2015
  2400 00004AC4 58                  <1> 	pop	eax
  2401 00004AC5 C605[53650000]00    <1> 	mov	byte [u.kcall], 0
  2402 00004ACC C3                  <1> 	retn	
  2403                              <1> dskr_1: 
  2404 00004ACD 3B15[10650000]      <1> 	cmp     edx, [u.count] 
  2405                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2406                              <1> 			       ; / to carry out read
  2407 00004AD3 7306                <1> 	jnb	short dskr_2
  2408                              <1> 		; bhis 1f
  2409 00004AD5 8915[10650000]      <1> 	mov	[u.count], edx
  2410                              <1> 		; mov r2,u.count / no, just read to end of file
  2411                              <1> dskr_2: ; 1:
  2412                              <1> 	; AX = i-number
  2413 00004ADB E89EFBFFFF          <1> 	call	mget
  2414                              <1> 		; jsr r0,mget / returns physical block number of block 
  2415                              <1> 			    ; / in file where offset points
  2416                              <1> 	; EAX = physical block number
  2417 00004AE0 E8CD080000          <1> 	call	dskrd
  2418                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2419                              <1> 			     ; / 1st word of data in buffer
  2420                              <1> 	; 09/06/2015
  2421 00004AE5 803D[53650000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2422 00004AEC 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2423 00004AEE 66833D[51650000]00  <1> 	cmp	word [u.pcount], 0
  2424 00004AF6 7705                <1> 	ja	short dskr_4
  2425                              <1> dskr_3:
  2426                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2427 00004AF8 E857000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2428                              <1> dskr_4:
  2429                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2430 00004AFD E83D030000          <1> 	call	sioreg
  2431                              <1> 		; jsr r0,sioreg
  2432                              <1> 
  2433                              <1> 	; 19/07/2022
  2434                              <1> 	;xchg	esi, edi
  2435                              <1> 	
  2436                              <1> 	; 19/07/2022
  2437                              <1> 	;  EDX = user data offset (previous value of [u.pbase])
  2438                              <1> 	;  ESI = pointer to file offset 
  2439                              <1> 	;  EDI = system (I/O) buffer offset
  2440                              <1> 	;  ECX = byte count
  2441                              <1> 	;  EBX = system buffer (data) address	
  2442                              <1> 	;  EAX = remain bytes after byte count within page frame 
  2443                              <1> 
  2444 00004B02 010E                <1> 	add	[esi], ecx 
  2445                              <1> 			; new file offset (old offset + byte count)
  2446                              <1> 	;
  2447 00004B04 89FE                <1> 	mov	esi, edi ; sector (I/O) buffer offset
  2448 00004B06 89D7                <1> 	mov	edi, edx
  2449                              <1> 
  2450                              <1> 	; EDI = file (user data) offset
  2451                              <1> 	; ESI = sector (I/O) buffer offset
  2452                              <1> 	; ECX = byte count
  2453 00004B08 F3A4                <1> 	rep	movsb
  2454                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2455                              <1> 		                 ; / starting at u.base
  2456                              <1> 		; dec r3
  2457                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2458                              <1> 	; 25/07/2015
  2459                              <1> 	; eax = remain bytes in buffer
  2460                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2461 00004B0A 09C0                <1> 	or	eax, eax
  2462 00004B0C 75EA                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2463                              <1> 	; 03/08/2013
  2464                              <1> 	;pop	eax
  2465 00004B0E 390D[10650000]      <1> 	cmp	[u.count], ecx ; 0
  2466                              <1> 		; tst u.count / all bytes read off disk
  2467                              <1> 		; bne dskr
  2468                              <1> 		; br ret
  2469                              <1>         ;ja	short dskr_0
  2470                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2471                              <1> 	;retn
  2472                              <1> 	; 12/10/2015
  2473 00004B14 76AE                <1> 	jna	short dskr_retn
  2474 00004B16 58                  <1> 	pop	eax  ; (i-node number)
  2475 00004B17 EB94                <1> 	jmp	short dskr_0
  2476                              <1> 	
  2477                              <1> passc:
  2478                              <1> 	; 18/10/2015
  2479                              <1> 	; 10/07/2015
  2480                              <1> 	; 01/07/2015
  2481                              <1> 	; 08/06/2015
  2482                              <1> 	; 04/06/2015
  2483                              <1> 	; 20/05/2015
  2484                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2485                              <1> 	;
  2486                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2487                              <1> 	;		      to physical address
  2488 00004B19 66833D[51650000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2489                              <1> 			     ; 1-4095 --> use previous physical base address
  2490                              <1> 			     ; in [u.pbase]
  2491 00004B21 7705                <1> 	ja	short passc_3
  2492                              <1> 	; 08/06/2015 - 10/07/2015
  2493 00004B23 E82C000000          <1> 	call	trans_addr_w
  2494                              <1> passc_3:
  2495                              <1> 	; 19/05/2015
  2496 00004B28 66FF0D[51650000]    <1> 	dec	word [u.pcount]
  2497                              <1> 	;
  2498 00004B2F 8B1D[4D650000]      <1> 	mov	ebx, [u.pbase]
  2499 00004B35 8803                <1> 	mov	[ebx], al
  2500                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2501                              <1> 		               ; / users buffer
  2502 00004B37 FF05[0C650000]      <1> 	inc	dword [u.base]
  2503                              <1> 		; inc u.base / increment the pointer to point to 
  2504                              <1> 			  ; / the next byte in users buffer
  2505 00004B3D FF05[4D650000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2506 00004B43 FF05[14650000]      <1> 	inc	dword [u.nread]
  2507                              <1> 		; inc u.nread / increment the number of bytes read
  2508 00004B49 FF0D[10650000]      <1> 	dec	dword [u.count]
  2509                              <1> 		; dec u.count / decrement the number of bytes to be read
  2510                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2511 00004B4F C3                  <1> 	retn
  2512                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2513                              <1> 		             ; / 'readi' by:
  2514                              <1> 		;/ (1) pop the return address off the stack into r0
  2515                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2516                              <1> 	;1:
  2517                              <1> 		; clr	*$ps / clear processor status
  2518                              <1> 		; rts r0 / return to address currently on top of stack
  2519                              <1> 
  2520                              <1> trans_addr_r:
  2521                              <1> 	; Translate virtual address to physical address 
  2522                              <1> 	; for reading from user's memory space
  2523                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2524                              <1> 	; 18/10/2015
  2525                              <1> 	; 10/07/2015
  2526                              <1> 	; 09/06/2015
  2527                              <1> 	; 08/06/2015 
  2528                              <1> 	; 04/06/2015
  2529                              <1> 	;
  2530                              <1> 	; 18/10/2015
  2531 00004B50 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2532 00004B52 EB04                <1> 	jmp 	short trans_addr_rw
  2533                              <1> 
  2534                              <1> 	;push	eax
  2535                              <1> 	;push	ebx
  2536                              <1> 	;mov	ebx, [u.base]
  2537                              <1> 	;call	get_physical_addr ; get physical address
  2538                              <1> 	;;jnc	short cpass_0
  2539                              <1> 	;jnc	short passc_1
  2540                              <1> 	;mov	[u.error], eax
  2541                              <1> 	;;pop	ebx
  2542                              <1> 	;;pop	eax
  2543                              <1> 	;jmp	error
  2544                              <1> ;cpass_0:
  2545                              <1> 	; 18/10/2015
  2546                              <1> 	; 20/05/2015
  2547                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2548                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2549                              <1> 	;pop	ebx
  2550                              <1> 	;pop	eax
  2551                              <1> 	;retn	; 08/06/2015
  2552                              <1> 
  2553                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2554                              <1> trans_addr_w:
  2555                              <1> 	; 31/12/2021
  2556                              <1> 	; Translate virtual address to physical address 
  2557                              <1> 	; for writing to user's memory space
  2558                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2559                              <1> 	; 18/10/2015
  2560                              <1> 	; 29/07/2015
  2561                              <1> 	; 10/07/2015
  2562                              <1> 	; 09/06/2015
  2563                              <1> 	; 08/06/2015
  2564                              <1> 	; 04/06/2015 (passc)
  2565                              <1> 	;
  2566                              <1> 	; 18/10/2015
  2567 00004B54 29D2                <1> 	sub	edx, edx
  2568 00004B56 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2569                              <1> trans_addr_rw:
  2570 00004B58 50                  <1> 	push	eax
  2571 00004B59 53                  <1> 	push	ebx
  2572                              <1> 	; 18/10/2015
  2573 00004B5A 52                  <1> 	push 	edx ; r/w sign (in DL)
  2574                              <1> 	;
  2575 00004B5B 8B1D[0C650000]      <1> 	mov	ebx, [u.base]
  2576 00004B61 E843DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2577 00004B66 730A                <1> 	jnc	short passc_0
  2578 00004B68 A3[41650000]        <1> 	mov	[u.error], eax
  2579                              <1> 	;pop	edx
  2580                              <1> 	;pop 	ebx
  2581                              <1> 	;pop	eax
  2582 00004B6D E959E5FFFF          <1> 	jmp	error
  2583                              <1> passc_0:
  2584 00004B72 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2585 00004B75 5A                  <1> 	pop	edx ; 18/10/2015
  2586 00004B76 7517                <1> 	jnz	short passc_1
  2587                              <1> 	; 18/10/2015
  2588 00004B78 20D2                <1> 	and 	dl, dl
  2589 00004B7A 7413                <1> 	jz	short passc_1
  2590                              <1> 	; 20/05/2015
  2591                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2592                              <1> 	; EBX = linear address
  2593 00004B7C 51                  <1> 	push 	ecx
  2594 00004B7D 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2595 00004B7E E897DBFFFF          <1> 	call 	copy_page
  2596 00004B83 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2597 00004B84 59                  <1> 	pop	ecx
  2598 00004B85 7217                <1> 	jc	short passc_2
  2599                              <1> 	; 24/12/2021
  2600                              <1> 	;push	eax ; physical address of the new/allocated page
  2601                              <1> 	;call	add_to_swap_queue
  2602                              <1> 	;pop	eax
  2603                              <1> 	; 18/10/2015
  2604 00004B87 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2605                              <1> 	;mov 	ecx, PAGE_SIZE
  2606                              <1> 	;sub	ecx, ebx 
  2607 00004B8D 01D8                <1> 	add	eax, ebx  
  2608                              <1> passc_1: 
  2609                              <1> 	; 18/10/2015
  2610                              <1> 	; 20/05/2015
  2611 00004B8F A3[4D650000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2612 00004B94 66890D[51650000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2613 00004B9B 5B                  <1> 	pop	ebx
  2614 00004B9C 58                  <1> 	pop	eax
  2615 00004B9D C3                  <1> 	retn	; 08/06/2015
  2616                              <1> passc_2:
  2617 00004B9E C705[41650000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2617 00004BA6 0000                <1>
  2618                              <1> 	;pop 	ebx
  2619                              <1> 	;pop	eax
  2620 00004BA8 E91EE5FFFF          <1> 	jmp	error
  2621                              <1> 
  2622                              <1> writei:
  2623                              <1> 	; 13/06/2022
  2624                              <1> 	; 03/02/2022
  2625                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2626                              <1> 	; 20/05/2015
  2627                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2628                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2629                              <1> 	;
  2630                              <1> 	; Write data to file with inode number in R1
  2631                              <1> 	; 
  2632                              <1> 	; INPUTS ->
  2633                              <1> 	;    r1 - inode number
  2634                              <1> 	;    u.count - byte count to be written
  2635                              <1> 	;    u.base - points to user buffer
  2636                              <1> 	;    u.fofp - points to word with current file offset
  2637                              <1> 	; OUTPUTS ->
  2638                              <1> 	;    u.count - cleared
  2639                              <1> 	;    u.nread - accumulates total bytes passed back	
  2640                              <1> 	; ((AX = R1))
  2641                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2642                              <1> 	;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -15/07/2022-
  2643                              <1> 
  2644 00004BAD 31C9                <1> 	xor	ecx, ecx
  2645 00004BAF 890D[14650000]      <1> 	mov 	[u.nread], ecx  ; 0
  2646                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2647                              <1> 		            ; / read or write calls
  2648 00004BB5 66890D[51650000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2649 00004BBC 390D[10650000]      <1> 	cmp 	[u.count], ecx
  2650                              <1> 	;	; tst u.count / test the byte count specified by the user
  2651 00004BC2 770B                <1> 	ja 	short writei_1 ; 1f
  2652                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2653                              <1> 
  2654                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2655 00004BC4 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2656 00004BC7 7505                <1> 	jne	short writei_0
  2657 00004BC9 E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2658                              <1> writei_0:
  2659 00004BCE C3                  <1> 	retn
  2660                              <1> 	;	; rts r0 / no, return - no writing to do
  2661                              <1> writei_1: ;1:
  2662                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2663 00004BCF 6683F828            <1> 	cmp 	ax, 40
  2664                              <1> 		; cmp r1,$40.
  2665                              <1> 		; / does the i-node number indicate a special file?
  2666                              <1> 	;ja	dskw 
  2667                              <1> 		; bgt dskw / no, branch to standard file output
  2668                              <1> 	; 24/12/2021
  2669 00004BD3 7605                <1> 	jna	short writei_3
  2670 00004BD5 E958010000          <1> 	jmp	dskw
  2671                              <1> writei_3:
  2672                              <1> 	; (20/05/2015)
  2673 00004BDA 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2674 00004BDB 0FB6D8              <1> 	movzx	ebx, al
  2675                              <1> 	; 03/02/2022
  2676 00004BDE C1E302              <1> 	shl	ebx, 2
  2677                              <1> 	;shl	bx, 2
  2678                              <1> 		; asl r1 / yes, calculate the index into the special file
  2679 00004BE1 81C3[E54B0000]      <1> 	add	ebx, writei_2 - 4
  2680 00004BE7 FF23                <1> 	jmp	dword [ebx]	
  2681                              <1> 		; jmp *1f-2(r1)
  2682                              <1> 		; / jump table and jump to the appropriate routine
  2683                              <1> writei_2: ;1:
  2684 00004BE9 [354C0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2685                              <1> 		 ;wtty / tty; r1=2
  2686                              <1> 		 ;wppt / ppt; r1=4
  2687 00004BED [884C0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2688                              <1> 		 ;wmem / mem; r1=6
  2689                              <1> 		 ;wrf0 / rf0
  2690                              <1> 		 ;wrk0 / rk0
  2691                              <1> 		 ;wtap / tap0
  2692                              <1> 		 ;wtap / tap1
  2693                              <1> 		 ;wtap / tap2
  2694                              <1> 		 ;wtap / tap3
  2695                              <1> 		 ;wtap / tap4
  2696                              <1> 		 ;wtap / tap5
  2697                              <1> 		 ;wtap / tap6
  2698                              <1> 		 ;wtap / tap7
  2699 00004BF1 [E8520000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2700 00004BF5 [E8520000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2701 00004BF9 [E8520000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2702 00004BFD [E8520000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2703 00004C01 [E8520000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2704 00004C05 [E8520000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2705 00004C09 [B84C0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2706 00004C0D [824C0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2707                              <1> 		 ;xmtt / tty0
  2708 00004C11 [824C0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2709                              <1> 		 ;xmtt / tty1
  2710 00004C15 [824C0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2711                              <1> 		 ;xmtt / tty2
  2712 00004C19 [824C0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2713                              <1> 		 ;xmtt / tty3
  2714 00004C1D [824C0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2715                              <1> 		 ;xmtt / tty4
  2716 00004C21 [824C0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2717                              <1> 		 ;xmtt / tty5
  2718 00004C25 [824C0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2719                              <1> 		 ;xmtt / tty6
  2720 00004C29 [824C0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2721                              <1> 		 ;xmtt / tty7
  2722 00004C2D [824C0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2723                              <1> 		; / wlpr / lpr
  2724 00004C31 [824C0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2725                              <1> 
  2726                              <1> wtty: ; write to console tty (write to screen)
  2727                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2728                              <1> 	; 18/11/2015
  2729                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2730                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2731                              <1> 	;
  2732                              <1> 	; Console tty output is on current video page
  2733                              <1> 	; Console tty character output procedure is changed here
  2734                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2735                              <1> 	;
  2736 00004C35 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2737 00004C3C 8AA3[43620000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2738 00004C42 88E0                <1> 	mov	al, ah ; 07/07/2014
  2739                              <1> wttys:	
  2740                              <1> 	; 10/10/2013
  2741 00004C44 8825[40650000]      <1> 	mov 	[u.ttyn], ah
  2742                              <1> 	; 13/01/2014
  2743 00004C4A FEC0                <1> 	inc	al
  2744 00004C4C A2[1D650000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2745                              <1> wtty_nc: ; 15/05/2013
  2746                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2747 00004C51 E889010000          <1> 	call	cpass
  2748                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2749                              <1> 		             ; / none go to return address in syswrite
  2750                              <1> 		; tst r1 / is character = null
  2751                              <1> 		; beq wtty / yes, get next character
  2752                              <1> 	; 10/10/2013
  2753 00004C56 7428                <1> 	jz	short wret
  2754                              <1> 	;1 : 
  2755                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2756                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2757                              <1> 		;	          / than 20
  2758                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2759                              <1> 	; 27/06/2014
  2760                              <1> wtty_1:
  2761                              <1> 	; AH = tty number
  2762                              <1> 	; AL = ASCII code of the character
  2763                              <1> 	; 15/04/2014
  2764                              <1> 	;push	ax
  2765                              <1> 	; 24/12/2021
  2766 00004C58 50                  <1> 	push	eax
  2767 00004C59 E88E090000          <1> 	call	putc ; 14/05/2013
  2768 00004C5E 731D                <1> 	jnc	short wtty_2
  2769                              <1> 	; 18/11/2015
  2770 00004C60 E814F9FFFF          <1> 	call	idle
  2771                              <1> 	;mov	ax, [esp]
  2772                              <1> 	; 24/12/2021
  2773 00004C65 8B0424              <1> 	mov	eax, [esp]
  2774 00004C68 E87F090000          <1> 	call	putc
  2775 00004C6D 730E                <1> 	jnc	short wtty_2 
  2776                              <1> 	; 02/06/2014
  2777 00004C6F 8A25[40650000]      <1> 	mov	ah, [u.ttyn]
  2778 00004C75 E88CF9FFFF          <1> 	call	sleep
  2779                              <1> 	;pop	ax
  2780                              <1> 	; 24/12/2021
  2781 00004C7A 58                  <1> 	pop	eax
  2782 00004C7B EBDB                <1> 	jmp 	short wtty_1
  2783                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2784                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2785                              <1> 			      ; / console tty and
  2786                              <1> 		; br 	2f / place character in list; if none available
  2787                              <1> 		   	  ; / branch to put process to sleep
  2788                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2789                              <1> wtty_2:
  2790                              <1> 	; 15/04/2014
  2791                              <1> 	;pop	ax
  2792                              <1> 	; 24/12/2021
  2793 00004C7D 58                  <1> 	pop	eax
  2794 00004C7E EBD1                <1> 	jmp	short wtty_nc
  2795                              <1> 		; br wtty
  2796                              <1> wret:	; 10/10/2013 (20/05/2015)
  2797 00004C80 58                  <1> 	pop	eax
  2798 00004C81 C3                  <1> 	retn
  2799                              <1> 	;2:
  2800                              <1> 		;mov	r1,-(sp) / place character on stack
  2801                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2802                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2803                              <1> 		;br	1b / try again to place character in clist and output
  2804                              <1> 
  2805                              <1> xmtt:   ; < send/write character to tty >
  2806                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2807                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2808                              <1> 	;
  2809                              <1> 	; Retro UNIX 8086 v1 modification !
  2810                              <1> 	; 
  2811                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2812                              <1> 	;		(exactly different than this one)
  2813                              <1> 	;	was in 'u9.s' file.
  2814                              <1> 	;
  2815 00004C82 2C0A                <1> 	sub 	al, 10
  2816                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2817                              <1> 	; 10/10/2013
  2818 00004C84 88C4                <1> 	mov	ah, al
  2819                              <1> 	; 28/07/2013
  2820 00004C86 EBBC                <1> 	jmp	short wttys
  2821                              <1> 
  2822                              <1> ;wppt:
  2823                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2824                              <1> ;		         / if none return to writei's calling routine
  2825                              <1> ;	jsr	r0,pptoc / output character on ppt
  2826                              <1> ;	br	wppt
  2827                              <1> 
  2828                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2829                              <1> 	; 17/10/2015
  2830                              <1> 	; 11/06/2015
  2831                              <1> 	; 24/05/2015
  2832                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2833                              <1> 	;
  2834 00004C88 813D[F1060000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2834 00004C8E [9C450000]          <1>
  2835 00004C92 7415                <1>         je      short wmem_acc_err
  2836                              <1> 	;
  2837 00004C94 8B35[FC640000]      <1>         mov     esi, [u.fofp] 
  2838                              <1> wmem_1:
  2839 00004C9A E840010000          <1> 	call	cpass
  2840                              <1> 		; jsr r0,cpass / get next character from users area of
  2841                              <1> 			     ; / core and put it in r1
  2842                              <1>         	; mov r1,-(sp) / put character on the stack
  2843                              <1> 	; 20/09/2013
  2844 00004C9F 74DF                <1> 	jz	short wret ; wmem_2  
  2845 00004CA1 8B1E                <1>         mov     ebx, [esi]
  2846                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2847 00004CA3 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2848                              <1> 		; inc *u.fofp / increment file offset to point to next
  2849                              <1> 			    ; / available location in file
  2850 00004CA5 8803                <1> 	mov	[ebx], al	
  2851                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2852                              <1> 			        ; / assigned to it
  2853 00004CA7 EBF1                <1> 	jmp	short wmem_1
  2854                              <1> 		; br wmem / continue
  2855                              <1> 	;1:
  2856                              <1> 	;jmp	error / ?
  2857                              <1> ;wmem_2:	
  2858                              <1> ;	; 20/09/2013
  2859                              <1> ;	pop	ax
  2860                              <1> ;	retn
  2861                              <1> 
  2862                              <1> wmem_acc_err:
  2863 00004CA9 C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2863 00004CB1 0000                <1>
  2864 00004CB3 E913E4FFFF          <1> 	jmp	error
  2865                              <1> 
  2866                              <1> ;wlpr:
  2867                              <1> 	; 13/06/2022
  2868                              <1> 	;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2869                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2870                              <1> 		;/	jsr	r0,cpass
  2871                              <1> 		;/	cmp	r0,$'a
  2872                              <1> 		;/	blo	1f
  2873                              <1> 		;/	cmp	r1,$'z
  2874                              <1> 		;/	bhi	1f
  2875                              <1> 		;/	sub	$40,r1
  2876                              <1> 		;/1:
  2877                              <1> 		;/	jsr	r0,lptoc
  2878                              <1> 		;/	br	wlpr
  2879                              <1> 		; br rmem / continue
  2880                              <1> 
  2881                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 - PRINTER BIOS (Functions)
  2882                              <1> 
  2883                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2884                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2885                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2886                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2887                              <1> 
  2888                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2889                              <1> 
  2890                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2891                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2892                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2893                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2894                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2895                              <1> RESERVED	equ 00000110b	; NOPS
  2896                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2897                              <1> 
  2898                              <1> ;----------------------------------------------------------------
  2899                              <1> ;								:
  2900                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2901                              <1> ;								:
  2902                              <1> ;   CX has count of bytes to be printed 			:
  2903                              <1> ;   ES:DI point to source buffer contains characters		:
  2904                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2905                              <1> ;								:
  2906                              <1> ;----------------------------------------------------------------
  2907                              <1> 
  2908                              <1> wlpr:
  2909                              <1> 	; 15/07/2022
  2910                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2911                              <1> PRN$WRIT:
  2912                              <1> 	; INPUT:
  2913                              <1> 	;	[u.count] = count of characters to be printed
  2914                              <1> 	;	[u.base] = buffer address in user's memory space
  2915                              <1> 	;
  2916                              <1> 	;	(if ECX = 0, printer status will be returned)
  2917                              <1> 	
  2918                              <1> 	;xor	ebx, ebx
  2919                              <1> PRN$LOOP:
  2920 00004CB8 E822010000          <1> 	call	cpass		  ; Get a character into AL
  2921 00004CBD 7431                <1> 	jz	short pr_exit
  2922                              <1> 	;
  2923 00004CBF B302                <1> 	mov	bl, 2  ; retry count
  2924                              <1> PRN$OUT:
  2925                              <1> 	; al = character which will be printed
  2926 00004CC1 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2927 00004CC3 E850000000          <1> 	call	PRNOP
  2928 00004CC8 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2929                              <1> PrRetry:
  2930                              <1> 	; al = character
  2931 00004CCA FECB                <1> 	dec	bl
  2932 00004CCC 75F3                <1> 	jnz	short PRN$OUT
  2933                              <1> pr_err_exit:
  2934 00004CCE 0FB6C0              <1> 	movzx	eax, al
  2935 00004CD1 A3[41650000]        <1> 	mov	[u.error], eax
  2936 00004CD6 A3[EC640000]        <1> 	mov	[u.r0], eax ; error code in AL
  2937                              <1> 	;mov 	ebp, [u.sp]
  2938 00004CDB 8B1D[E4640000]      <1> 	mov	ebx, [u.sp] ; 15/07/2022
  2939                              <1> 			; Kernel stack at the beginning of sys call
  2940 00004CE1 8B15[14650000]      <1> 	mov	edx, [u.nread]
  2941 00004CE7 4A                  <1> 	dec	edx ; last char failed
  2942                              <1> 	;mov	[ebp+20], edx ; count of printed characters in edx
  2943 00004CE8 895314              <1> 	mov	[ebx+20], edx ; 15/07/2022
  2944 00004CEB E9DBE3FFFF          <1> 	jmp	error
  2945                              <1> pr_exit:
  2946 00004CF0 58                  <1> 	pop	eax ; inode number
  2947                              <1> 
  2948                              <1> 	;mov	eax, [u.nread]
  2949                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2950                              <1> 	;jmp	sysret
  2951 00004CF1 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2952                              <1> 
  2953                              <1> ; 13/06/2022
  2954                              <1> 
  2955                              <1> ;----------------------------------------------------------------
  2956                              <1> ;								:
  2957                              <1> ;		PRINTER STATUS ROUTINE				:
  2958                              <1> ;								:
  2959                              <1> ;----------------------------------------------------------------
  2960                              <1> ;
  2961                              <1> 
  2962                              <1> lpr_stat:
  2963                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2964                              <1> PRN$STAT:
  2965 00004CF2 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2966 00004CF7 750E                <1> 	jnz	short prn_stat_retn
  2967                              <1> 				  ; if error jump to error routine
  2968                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2969 00004CF9 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2970 00004CFB F6C420              <1> 	test	ah, NOPAPERSTATUS
  2971 00004CFE 7507                <1> 	jnz	short prn_stat_retn
  2972 00004D00 F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2973 00004D03 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2974 00004D05 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2975                              <1> prn_stat_retn:
  2976                              <1> 	; al = error code
  2977                              <1> 	; ah = status flags
  2978 00004D07 A3[EC640000]        <1> 	mov	[u.r0], eax
  2979                              <1> 	;movzx	eax, al
  2980                              <1> 	;mov 	[u.error], eax
  2981 00004D0C 58                  <1> 	pop	eax ; discard return address to syswrite
  2982 00004D0D E9D9E3FFFF          <1> 	jmp	sysret
  2983                              <1> prn_stat_ok:
  2984 00004D12 30C0                <1> 	xor	al, al ; 0
  2985 00004D14 EBF1                <1> 	jmp	short prn_stat_retn
  2986                              <1> 
  2987                              <1> ;
  2988                              <1> ;   PRNSTAT	get printer status
  2989                              <1> ;   PRNOP	print a character
  2990                              <1> ;
  2991                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2992                              <1> ; printer routines.  The routines share code which calls on the bios and
  2993                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2994                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2995                              <1> ;
  2996                              <1> ;   INPUT	if PRNOP then character in AL
  2997                              <1> ;
  2998                              <1> ;   OUTPUT	- AL holds error code
  2999                              <1> ;		- AH status byte from printer
  3000                              <1> ;		- flag NZ if error
  3001                              <1> 
  3002                              <1> PRNSTAT:
  3003 00004D16 B402                <1> 	mov	ah, 2		  ; set command for get status 
  3004                              <1> 
  3005                              <1> PRNOP:
  3006                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  3007                              <1> 	;
  3008                              <1> 	; Print character (on paper)
  3009                              <1> 
  3010                              <1> 	; INPUT:
  3011                              <1> 	;	al = character to be printed
  3012                              <1> 	; OUTPUT:
  3013                              <1> 	;	zf = 1 -> ok
  3014                              <1> 	;	zf = 0 -> error code in AL
  3015                              <1> 
  3016 00004D18 E8080B0000          <1> 	call	int17h	 ; call lpt bios
  3017                              <1> 	
  3018 00004D1D F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  3019 00004D20 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  3020                              <1> 
  3021                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  3022                              <1> 	; THE CONVERSE IS NOT TRUE.
  3023                              <1> 
  3024                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  3025 00004D22 B01F                <1> 	mov	al, ERR_PRN_PAPER
  3026 00004D24 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  3027 00004D27 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  3028                              <1> 	;mov	al, ERR_PRN_IO
  3029 00004D29 FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  3030                              <1> PRNOP1: 
  3031                              <1> 
  3032                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  3033                              <1> 
  3034 00004D2B C3                  <1> 	retn			  ; RETURN WITH ERROR
  3035                              <1>  
  3036                              <1> ; THE BITS SAID NO ERROR.
  3037                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  3038                              <1> 
  3039                              <1> prnop_chk_nrdy:
  3040                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  3041 00004D2C B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  3042                              <1> 	
  3043 00004D2E F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  3044                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  3045                              <1> PRNOP2: 
  3046 00004D31 C3                  <1> 	retn
  3047                              <1> 
  3048                              <1> 
  3049                              <1> dskw: ; / write routine for non-special files
  3050                              <1> 	;
  3051                              <1> 	; 19/07/2022
  3052                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  3053                              <1> 	;
  3054                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3055                              <1> 	; 25/07/2015
  3056                              <1> 	; 16/06/2015
  3057                              <1> 	; 09/06/2015
  3058                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  3059                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  3060                              <1> 	;
  3061                              <1> 	; 01/08/2013 (mkdir_w check)
  3062                              <1> 
  3063                              <1> 	;push	ax ; 26/04/2013
  3064                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  3065                              <1> 	; 24/12/2021
  3066 00004D32 50                  <1> 	push	eax
  3067                              <1> 	; AX = inode number
  3068 00004D33 E8AFFAFFFF          <1> 	call	iget
  3069                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  3070                              <1> 		            ; / read i-node 'r1' into i-node area of core
  3071 00004D38 8B1D[FC640000]      <1>         mov     ebx, [u.fofp] 
  3072 00004D3E 8B13                <1> 	mov 	edx, [ebx]
  3073                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  3074                              <1> 			       ; / in the fsp entry for this file] in r2
  3075 00004D40 0315[10650000]      <1> 	add 	edx, [u.count]	
  3076                              <1> 		; add u.count,r2 / no. of bytes to be written
  3077                              <1> 			       ; / + file offset is put in r2
  3078                              <1> 	; 16/06/2015        
  3079 00004D46 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  3080 00004D4C 760F                <1> 	jna	short dskw_0
  3081 00004D4E C705[41650000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  3081 00004D56 0000                <1>
  3082 00004D58 E96EE3FFFF          <1> 	jmp	error
  3083                              <1> dskw_0:	
  3084 00004D5D 663B15[E8610000]    <1> 	cmp     dx, [i.size]
  3085                              <1> 		; cmp r2,i.size / is this greater than the present size of
  3086                              <1> 		              ; / the file?
  3087 00004D64 760C                <1> 	jna	short dskw_1
  3088                              <1> 		; blos 1f / no, branch
  3089 00004D66 668915[E8610000]    <1>         mov     [i.size], dx
  3090                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3091                              <1> 			      ; / file offset + no. of data bytes
  3092 00004D6D E87FFBFFFF          <1> 	call	setimod
  3093                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3094                              <1> 		          ; / modified), stuff time of modification into
  3095                              <1> 	          	  ; / core image of i-node
  3096                              <1> dskw_1: ; 1:	
  3097 00004D72 E807F9FFFF          <1> 	call	mget
  3098                              <1> 	; EAX = Block number
  3099                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3100                              <1> 			    ; /	the next data byte
  3101                              <1> 	; eax = block number
  3102 00004D77 8B1D[FC640000]      <1> 	mov     ebx, [u.fofp]
  3103 00004D7D 8B13                <1> 	mov	edx, [ebx]
  3104 00004D7F 81E2FF010000        <1> 	and	edx, 1FFh  
  3105                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3106 00004D85 750C                <1> 	jnz	short dskw_2
  3107                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3108                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3109 00004D87 813D[10650000]0002- <1> 	cmp	dword [u.count], 512
  3109 00004D8F 0000                <1>
  3110                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3111                              <1> 				  ; / an entire block? (i.e., no. of
  3112 00004D91 7305                <1> 	jnb	short dskw_3
  3113                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3114                              <1> 			; / Yes, branch. Don't have to read block
  3115                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3116                              <1>    		; / overwritten).
  3117 00004D93 E81A060000          <1> 	call	dskrd
  3118                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3119                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3120                              <1> dskw_3: ; 3:
  3121                              <1> 	; EAX (r1) = block/sector number
  3122 00004D98 E879060000          <1> 	call	wslot
  3123                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3124                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3125 00004D9D 803D[53650000]00    <1> 	cmp	byte [u.kcall], 0
  3126 00004DA4 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3127                              <1> 	;
  3128 00004DA6 66833D[51650000]00  <1> 	cmp	word [u.pcount], 0
  3129 00004DAE 7705                <1> 	ja	short dskw_5
  3130                              <1> dskw_4:
  3131                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3132 00004DB0 E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3133                              <1> dskw_5:
  3134                              <1> 	; EBX (r5) = system (I/O) buffer address
  3135 00004DB5 E885000000          <1> 	call	sioreg
  3136                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3137                              <1> 			     ; / r1 = address of data, r2 points to location
  3138                              <1> 			     ; / in buffer in which to start writing data
  3139                              <1> 	; 19/07/2022
  3140                              <1> 	;  EDX = user data offset (previous value of [u.pbase])
  3141                              <1> 	;  ESI = pointer to file offset 
  3142                              <1> 	;  EDI = system (I/O) buffer offset
  3143                              <1> 	;  ECX = byte count
  3144                              <1> 	;  EBX = system buffer (data) address	
  3145                              <1> 	;  EAX = remain bytes after byte count within page frame 
  3146                              <1> 
  3147                              <1> 	; 19/07/2022 - Erdogan Tan
  3148                              <1> 	; BugFix (Also original unix v1 kernel code has this bug!)
  3149                              <1> 	; ((Against a possible disk write failure/error, 
  3150                              <1> 	;   file offset must not be updated/increased before 'dskwr'
  3151                              <1> 	;   but it was updated in 'sioreg'. I have modified 'sioreg'
  3152                              <1> 	;   and 'dskw' procedures for that.))
  3153                              <1> 
  3154                              <1> 	; 19/07/2022
  3155 00004DBA 56                  <1> 	push	esi ; *	 ; save file offset (pointer)
  3156 00004DBB 51                  <1> 	push	ecx ; ** ; save byte count
  3157 00004DBC 89D6                <1> 	mov	esi, edx
  3158                              <1> 
  3159                              <1> 	; ESI = file (user data) offset
  3160                              <1> 	; EDI = sector (I/O) buffer offset
  3161                              <1> 	; ECX = byte count
  3162                              <1> 	;
  3163 00004DBE F3A4                <1>   	rep	movsb
  3164                              <1> 		; movb (r1 )+,(r2)+ 
  3165                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3166                              <1> 		; dec r3 / decrement no. of bytes to be written
  3167                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3168                              <1> 	; 25/07/2015
  3169                              <1> 	; eax = remain bytes in buffer
  3170                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3171 00004DC0 09C0                <1> 	or	eax, eax
  3172 00004DC2 75EC                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)
  3173                              <1> dskw_6:
  3174 00004DC4 E85A060000          <1> 	call	dskwr
  3175                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3176                              <1> 
  3177                              <1> 	; 19/07/2022
  3178                              <1> 	; (there is not a disk write error, we can increase file offset)
  3179 00004DC9 58                  <1> 	pop	eax ; ** ; byte count
  3180 00004DCA 5F                  <1> 	pop	edi ; *  ; file offset (pointer)
  3181                              <1> 	;
  3182 00004DCB 0107                <1> 	add	[edi], eax
  3183                              <1> 			; new file offset (old offset + byte count)
  3184                              <1> 
  3185 00004DCD 833D[10650000]00    <1>         cmp     dword [u.count], 0
  3186                              <1> 		; tst u.count / any more data to write?
  3187 00004DD4 779C                <1> 	ja	short dskw_1
  3188                              <1> 		; bne 1b / yes, branch
  3189                              <1> 	; 03/08/2013
  3190 00004DD6 C605[53650000]00    <1> 	mov	byte [u.kcall], 0
  3191                              <1> 	; 20/09/2013 (;;)
  3192                              <1> 	;pop	ax
  3193                              <1> 	; 24/12/2021
  3194 00004DDD 58                  <1> 	pop	eax
  3195 00004DDE C3                  <1> 	retn
  3196                              <1> 	;;jmp 	short dskw_ret 
  3197                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3198                              <1> 
  3199                              <1> cpass: ; / get next character from user area of core and put it in r1
  3200                              <1> 	; 18/10/2015
  3201                              <1> 	; 10/10/2015
  3202                              <1> 	; 10/07/2015
  3203                              <1> 	; 02/07/2015
  3204                              <1> 	; 01/07/2015
  3205                              <1> 	; 24/06/2015
  3206                              <1> 	; 08/06/2015
  3207                              <1> 	; 04/06/2015
  3208                              <1> 	; 20/05/2015
  3209                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3210                              <1> 	;
  3211                              <1> 	; INPUTS -> 
  3212                              <1> 	;     [u.base] = virtual address in user area
  3213                              <1> 	;     [u.count] = byte count (max.)
  3214                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3215                              <1> 	; OUTPUTS -> 
  3216                              <1> 	;     AL = the character which is pointed by [u.base]
  3217                              <1> 	;     zf = 1 -> transfer count has been completed	
  3218                              <1>         ;
  3219                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3220                              <1> 	;
  3221                              <1> 	;
  3222 00004DDF 833D[10650000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3223                              <1> 		; tst u.count / have all the characters been transferred
  3224                              <1> 			    ; / (i.e., u.count, # of chars. left
  3225 00004DE6 763F                <1> 	jna	short cpass_3
  3226                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3227 00004DE8 FF0D[10650000]      <1> 	dec	dword [u.count]
  3228                              <1> 		; dec u.count / no, decrement u.count
  3229                              <1>         ; 19/05/2015 
  3230                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3231                              <1> 	;		      to physical address
  3232 00004DEE 66833D[51650000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3233                              <1> 			     ; 1-4095 --> use previous physical base address
  3234                              <1> 			     ; in [u.pbase]
  3235 00004DF6 770E                <1> 	ja	short cpass_1
  3236                              <1> 	; 02/07/2015
  3237 00004DF8 833D[49650000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3238 00004DFF 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3239                              <1> 	; 08/06/2015 - 10/07/2015
  3240 00004E01 E84AFDFFFF          <1> 	call	trans_addr_r
  3241                              <1> cpass_1:
  3242                              <1> 	; 02/07/2015
  3243                              <1> 	; 24/06/2015
  3244 00004E06 66FF0D[51650000]    <1> 	dec	word [u.pcount]
  3245                              <1> cpass_2: 
  3246                              <1> 	; 10/10/2015
  3247                              <1> 	; 02/07/2015
  3248 00004E0D 8B15[4D650000]      <1> 	mov	edx, [u.pbase]
  3249 00004E13 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3250                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3251                              <1> 				; / by u.base and put it in r1
  3252 00004E15 FF05[14650000]      <1> 	inc	dword [u.nread]
  3253                              <1> 		; inc u.nread / increment no. of bytes transferred
  3254 00004E1B FF05[0C650000]      <1> 	inc	dword [u.base]
  3255                              <1> 		; inc u.base / increment the buffer address to point to the
  3256                              <1> 			   ; / next byte
  3257 00004E21 FF05[4D650000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3258                              <1> cpass_3:
  3259 00004E27 C3                  <1> 	retn
  3260                              <1> 		; rts	r0 / next byte
  3261                              <1> 	; 1: 
  3262                              <1> 		; mov (sp)+,r0 
  3263                              <1> 		         ; / put return address of calling routine into r0
  3264                              <1> 		; mov (sp)+,r1 / i-number in r1
  3265                              <1> 		; rts r0 / non-local return
  3266                              <1> cpass_k:
  3267                              <1> 	; 02/07/2015
  3268                              <1> 	; The caller is os kernel 
  3269                              <1> 	; (get sysexec arguments from kernel's memory space)
  3270                              <1> 	;
  3271 00004E28 8B1D[0C650000]      <1> 	mov	ebx, [u.base]
  3272 00004E2E 66C705[51650000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3272 00004E36 10                  <1>
  3273 00004E37 891D[4D650000]      <1> 	mov	[u.pbase], ebx
  3274 00004E3D EBCE                <1> 	jmp	short cpass_2
  3275                              <1> 	
  3276                              <1> sioreg:
  3277                              <1> 	; 19/07/2022
  3278                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  3279                              <1> 	; 25/07/2015
  3280                              <1> 	; 18/07/2015
  3281                              <1> 	; 02/07/2015
  3282                              <1> 	; 17/06/2015
  3283                              <1> 	; 09/06/2015
  3284                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3285                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3286                              <1> 	;
  3287                              <1> 	; INPUTS -> 
  3288                              <1> 	;     EBX = system buffer (data) address (r5)
  3289                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3290                              <1> 	;     [u.base] = virtual address of the user buffer
  3291                              <1> 	;     [u.pbase] = physical address of the user buffer
  3292                              <1> 	;     [u.count] = byte count
  3293                              <1> 	;     [u.pcount] = byte count within page frame 			
  3294                              <1> 	; OUTPUTS -> 
  3295                              <1> 	;     ESI = user data offset (r1)
  3296                              <1> 	;     EDI = system (I/O) buffer offset (r2)
  3297                              <1> 	;     ECX = byte count (r3)
  3298                              <1> 	;     EAX = remain bytes after byte count within page frame
  3299                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3300                              <1>         ;
  3301                              <1> 	; ((Modified registers:  EDX))
  3302                              <1> 
  3303                              <1> 	; 19/07/2022
  3304                              <1> 	; OUTPUTS -> 
  3305                              <1> 	;	EDX = user data offset (previous value of [u.pbase])
  3306                              <1> 	;	ESI = pointer to file offset 
  3307                              <1> 	; 	EDI = system (I/O) buffer offset
  3308                              <1> 	;	ECX = byte count
  3309                              <1> 	;	EBX = system buffer (data) address	
  3310                              <1> 	;	EAX = remain bytes after byte count within page frame
  3311                              <1>  
  3312 00004E3F 8B35[FC640000]      <1>         mov     esi, [u.fofp]
  3313 00004E45 8B3E                <1>         mov     edi, [esi]
  3314                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3315 00004E47 89F9                <1> 	mov	ecx, edi
  3316                              <1> 		; mov r2,r3 / and also to r3
  3317 00004E49 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3318                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3319 00004E4F 81E7FF010000        <1> 	and	edi, 1FFh
  3320                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3321 00004E55 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3322                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3323                              <1> 			  ; / where data is to be placed
  3324                              <1>                 ; mov u.base,r1 / address of data is in r1
  3325 00004E57 F7D9                <1> 	neg	ecx
  3326                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3327                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3328 00004E59 3B0D[10650000]      <1> 	cmp	ecx, [u.count]
  3329                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3330                              <1> 			       ; / to be written to the file
  3331 00004E5F 7606                <1> 	jna	short sioreg_0
  3332                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3333                              <1> 			 ; / in the file block as the number to be written
  3334 00004E61 8B0D[10650000]      <1> 	mov	ecx, [u.count]
  3335                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3336                              <1> 			       ; / bytes as the number to be written
  3337                              <1> sioreg_0:
  3338                              <1> 	; 17/06/2015
  3339 00004E67 803D[53650000]00    <1> 	cmp	byte [u.kcall], 0 
  3340 00004E6E 7613                <1> 	jna	short sioreg_1
  3341                              <1> 	; 25/07/2015
  3342                              <1> 	; the caller is 'mkdir' or 'namei'
  3343 00004E70 A1[0C650000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3344 00004E75 A3[4D650000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3345 00004E7A 66890D[51650000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3346 00004E81 EB0B                <1> 	jmp	short sioreg_2
  3347                              <1> sioreg_1:
  3348                              <1> 	; 25/07/2015
  3349                              <1> 	; 18/07/2015
  3350                              <1> 	; 09/06/2015 
  3351 00004E83 0FB715[51650000]    <1> 	movzx	edx, word [u.pcount]
  3352                              <1> 		; ecx and [u.pcount] are always > 0, here
  3353 00004E8A 39D1                <1> 	cmp	ecx, edx	
  3354 00004E8C 7728                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3355                              <1> sioreg_2: ; 2:
  3356 00004E8E 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3357                              <1> sioreg_3:
  3358 00004E90 010D[14650000]      <1> 	add 	[u.nread], ecx
  3359                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3360                              <1> 			         ; / during write is put into u.nread
  3361 00004E96 290D[10650000]      <1> 	sub 	[u.count], ecx
  3362                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3363                              <1> 			       ; / must be written or read
  3364 00004E9C 010D[0C650000]      <1> 	add 	[u.base], ecx
  3365                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3366                              <1> 			      ; / data bytes
  3367                              <1>         ; 19/07/2022
  3368                              <1> 	;add 	[esi], ecx 
  3369                              <1> 	;	; add r3,*u.fofp / new file offset = number of bytes done
  3370                              <1> 			       ; / + old file offset
  3371                              <1> 	; 25/07/2015
  3372                              <1> 	;mov	esi, [u.pbase]
  3373                              <1> 	; 19/07/2022
  3374 00004EA2 8B15[4D650000]      <1> 	mov	edx, [u.pbase]
  3375                              <1> 
  3376 00004EA8 66290D[51650000]    <1> 	sub	[u.pcount], cx
  3377 00004EAF 010D[4D650000]      <1> 	add	[u.pbase], ecx
  3378 00004EB5 C3                  <1>         retn
  3379                              <1> 		; rts r0
  3380                              <1> 		; transfer count > [u.pcount]
  3381                              <1> sioreg_4:
  3382                              <1> 	; 25/07/2015
  3383                              <1> 	; transfer count > [u.pcount] 
  3384                              <1> 	; (ecx > edx)
  3385 00004EB6 89C8                <1> 	mov	eax, ecx
  3386 00004EB8 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3387 00004EBA 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3388 00004EBC EBD2                <1> 	jmp	short sioreg_3
  2120                                  %include 'u7.s'        ; 18/04/2015
  2121                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS7.INC
  2122                              <1> ; Last Modification: 13/06/2022
  2123                              <1> ; ----------------------------------------------------------------------------
  2124                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2125                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2126                              <1> ;
  2127                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2128                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2129                              <1> ; <Bell Laboratories (17/3/1972)>
  2130                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2131                              <1> ;
  2132                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2133                              <1> ;
  2134                              <1> ; ****************************************************************************
  2135                              <1> 
  2136                              <1> sysmount: ; / mount file system; args special; name
  2137                              <1> 	; 15/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2138                              <1> 	; 09/02/2022
  2139                              <1> 	; 08/02/2022
  2140                              <1> 	; 07/02/2022
  2141                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2142                              <1> 	; 14/11/2015
  2143                              <1> 	; 24/10/2015
  2144                              <1> 	; 13/10/2015
  2145                              <1> 	; 10/07/2015
  2146                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2147                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2148                              <1> 	;
  2149                              <1> 	; 'sysmount' anounces to the system that a removable 
  2150                              <1> 	; file system has been mounted on a special file.
  2151                              <1> 	; The device number of the special file is obtained via
  2152                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2153                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2154                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2155                              <1> 	; to read file system into core, i.e. the first block on the
  2156                              <1> 	; mountable file system is read in. This block is super block
  2157                              <1> 	; for the file system. This call is super user restricted.	
  2158                              <1> 	;
  2159                              <1> 	; Calling sequence:
  2160                              <1> 	;	sysmount; special; name
  2161                              <1> 	; Arguments:
  2162                              <1> 	;	special - pointer to name of special file (device)
  2163                              <1> 	;	name -  pointer to name of the root directory of the
  2164                              <1> 	;		newly mounted file system. 'name' should 
  2165                              <1> 	;		always be a directory.
  2166                              <1> 	; Inputs: - 
  2167                              <1> 	; Outputs: -
  2168                              <1> 	; ...............................................................
  2169                              <1> 	;				
  2170                              <1> 	; Retro UNIX 8086 v1 modification: 
  2171                              <1> 	;       'sysmount' system call has two arguments; so,
  2172                              <1> 	;	* 1st argument, special is pointed to by BX register
  2173                              <1> 	;	* 2nd argument, name is in CX register
  2174                              <1> 	;
  2175                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2176                              <1> 	;	       already modified for IBM PC compatibility and 
  2177                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2178                              <1> 	
  2179                              <1> 	;call	arg2
  2180                              <1> 		; jsr r0,arg2 / get arguments special and name
  2181 00004EBE 891D[04650000]      <1> 	mov	[u.namep], ebx
  2182                              <1> 	; 09/02/2022
  2183                              <1> 	;push	ecx ; directory name
  2184 00004EC4 66833D[D6640000]00  <1> 	cmp	word [mnti], 0
  2185                              <1> 		; tst mnti / is the i-number of the cross device file
  2186                              <1> 			 ; / zero?
  2187                              <1> 	;;ja	error
  2188                              <1>         	; bne errora / no, error
  2189                              <1> 	;ja	sysmnt_err0
  2190                              <1> 	; 11/01/2022
  2191 00004ECC 7605                <1> 	jna	short sysmnt_0
  2192 00004ECE E968010000          <1> 	jmp	sysmnt_err0
  2193                              <1> sysmnt_0:
  2194                              <1> 	; 09/02/2022
  2195 00004ED3 51                  <1> 	push	ecx ; directory name
  2196 00004ED4 E84A010000          <1> 	call	getspl
  2197                              <1> 		; jsr r0,getspl / get special files device number in r1
  2198                              <1> 	; 09/02/2022
  2199 00004ED9 8F05[04650000]      <1> 	pop	dword [u.namep] ; directory name
  2200                              <1> 	; 13/10/2015
  2201                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2202                              <1> 	; 11/01/2022
  2203 00004EDF 29DB                <1> 	sub	ebx, ebx
  2204 00004EE1 88C3                <1> 	mov	bl, al
  2205 00004EE3 F683[6E5C0000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2206 00004EEA 750F                <1> 	jnz	short sysmnt_1
  2207                              <1> sysmnt_err1:
  2208 00004EEC C705[41650000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2208 00004EF4 0000                <1>
  2209 00004EF6 E9D0E1FFFF          <1> 	jmp	error
  2210                              <1> sysmnt_1:
  2211                              <1> 	; 09/02/2022
  2212                              <1> 	;pop	dword [u.namep]
  2213                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2214                              <1> 				  ; / on the device
  2215                              <1> 	; 14/11/2015
  2216 00004EFB 53                  <1> 	push	ebx ; 13/10/2015
  2217                              <1> 		; mov r1,-(sp) / save the device number
  2218                              <1>         ;
  2219 00004EFC E8D6F0FFFF          <1> 	call	namei
  2220                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2221                              <1> 		       ; ax = 0 -> file not found 	
  2222                              <1> 	;jz	error
  2223                              <1> 	;jc	error
  2224                              <1> 		; jsr r0,namei / get the i-number of the file
  2225                              <1>                	; br errora
  2226 00004F01 730F                <1> 	jnc	short sysmnt_2
  2227                              <1> sysmnt_err2:
  2228 00004F03 C705[41650000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2228 00004F0B 0000                <1>
  2229 00004F0D E9B9E1FFFF          <1> 	jmp	error
  2230                              <1> sysmnt_2:	
  2231 00004F12 66A3[D6640000]      <1> 	mov	[mnti], ax
  2232                              <1>         	; mov r1,mnti / put it in mnti
  2233                              <1> 
  2234                              <1> 	; 15/05/2022
  2235                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2236 00004F18 66A1[D0640000]      <1> 	mov	ax, [ii]
  2237 00004F1E 66A3[D8640000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2238                              <1> 
  2239                              <1> 	; 11/01/2022
  2240 00004F24 BB[BC770000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2241                              <1> sysmnt_3: ;1:
  2242                              <1>         ;cmp	byte [ebx+1], 0
  2243                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2244                              <1> 			   ; / dismountable device set?
  2245                              <1>         ;jna	short sysmnt_4		
  2246                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2247                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2248                              <1> 	;jmp	short sysmnt_3
  2249                              <1> sysmnt_4:   
  2250 00004F29 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2251 00004F2A A2[D5640000]        <1> 	mov	[mdev], al
  2252                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2253 00004F2F 8803                <1> 	mov	[ebx], al
  2254                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2255                              <1> 			      ; / of the I/O queue entry
  2256                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2257                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2258 00004F31 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2259                              <1> 		; bis $2000,sb1 / set the read bit
  2260                              <1> 	; Retro UNIX 386 v1 modification : 
  2261                              <1> 	;	32 bit block number at buffer header offset 4
  2262 00004F36 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2263 00004F3D E8AB050000          <1> 	call 	diskio
  2264 00004F42 7345                <1> 	jnc	short sysmnt_5
  2265 00004F44 31C0                <1> 	xor 	eax, eax
  2266 00004F46 66A3[D6640000]      <1> 	mov	[mnti], ax ; 0
  2267 00004F4C A2[D5640000]        <1> 	mov	[mdev], al ; 0
  2268                              <1> 	;mov	[cdev], al ; 0
  2269                              <1> 	; 08/02/2022
  2270 00004F51 803D[54650000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2271 00004F58 7508                <1> 	jne	short sysmnt_err3
  2272                              <1> 	; yes, clear [u.brwdev] for next check
  2273                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2274 00004F5A FE05[54650000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2275 00004F60 EB0A                <1> 	jmp	short sysmnt_err4
  2276                              <1> sysmnt_err3:	; 08/02/2022
  2277                              <1> 	; no, set [u.error] to disk read error
  2278 00004F62 C705[41650000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2278 00004F6A 0000                <1>
  2279                              <1> sysmnt_err4:
  2280                              <1> 	; 08/02/2022
  2281                              <1> 	; 14/11/2015
  2282 00004F6C FEC8                <1> 	dec 	al
  2283 00004F6E 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2284 00004F70 FEC0                <1> 	inc	al
  2285 00004F72 48                  <1> 	dec	eax
  2286 00004F73 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2287 00004F76 E950E1FFFF          <1> 	jmp	error
  2288                              <1> sysmnt_invd:
  2289                              <1> 	; 08/02/2022
  2290 00004F7B C705[41650000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2290 00004F83 0000                <1>
  2291                              <1> 				 ;'invalid fs/superblock !' error
  2292 00004F85 30C0                <1> 	xor	al, al
  2293 00004F87 EBE3                <1> 	jmp	short sysmnt_err4	
  2294                              <1> 
  2295                              <1> sysmnt_5:
  2296                              <1> 	; 08/02/2022
  2297                              <1> 	; 11/01/2022 (BugFix)
  2298                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2299                              <1> 	; (Following check is needed to prevent mounting an
  2300                              <1> 	; invalid file system (invalid super block).
  2301                              <1> 	; 
  2302 00004F89 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2303 00004F8C C0E002              <1> 	shl	al, 2 ; 4*index
  2304 00004F8F 8B88[525C0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2305 00004F95 C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2306                              <1> 	; ecx = number of free map bytes (required)
  2307                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2308 00004F98 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2309                              <1> 	; edx = number of free blocks map bytes
  2310                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2311                              <1> 	; 07/02/2022
  2312                              <1> 	;xor	al, al ; 08/02/2022
  2313 00004F9C 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2314                              <1> 			 ; (in sectors), if they are not equal
  2315                              <1> 			 ; the disk to be mounted is an...	
  2316 00004F9E 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2317                              <1> 			 ; (which has not got a valid super block)
  2318                              <1> 	;
  2319 00004FA0 C6430100            <1> 	mov	byte [ebx+1], 0
  2320                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2321                              <1> ;sysmnt_6: ;1:
  2322                              <1> 	;;cmp	byte [sb1+1], 0
  2323                              <1> 		; tstb sb1+1 / done reading?
  2324                              <1>    	;;jna	sysret
  2325                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2326                              <1> 	;;jmp	short sysmnt_6
  2327                              <1> 		; bne 1b / no, wait
  2328                              <1>         	; br sysreta / yes
  2329 00004FA4 E942E1FFFF          <1> 	jmp	sysret
  2330                              <1> 
  2331                              <1> sysumount: ; / special dismount file system
  2332                              <1> 	; 15/05/2022
  2333                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2334                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2335                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2336                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2337                              <1> 	;
  2338                              <1> 	; 04/11/2013
  2339                              <1> 	; 09/07/2013
  2340                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2341                              <1> 	; indicated as an argument is no longer contain a removable
  2342                              <1> 	; file system. 'getspl' gets the device number of the special
  2343                              <1> 	; file. If no file system was mounted on that device an error
  2344                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2345                              <1> 	; to 'sysret'.
  2346                              <1> 	;
  2347                              <1> 	; Calling sequence:
  2348                              <1> 	;	sysmount; special
  2349                              <1> 	; Arguments:
  2350                              <1> 	;	special - special file to dismount (device)
  2351                              <1> 	;
  2352                              <1> 	; Inputs: - 
  2353                              <1> 	; Outputs: -
  2354                              <1> 	; ...............................................................
  2355                              <1> 	;				
  2356                              <1> 	; Retro UNIX 8086 v1 modification: 
  2357                              <1> 	;       'sysumount' system call has one argument; so,
  2358                              <1> 	;	* Single argument, special is pointed to by BX register
  2359                              <1> 	;
  2360                              <1> 	
  2361                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2362                              <1> 	;call	arg
  2363                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2364 00004FA9 891D[04650000]      <1>         mov	[u.namep], ebx
  2365 00004FAF E86F000000          <1> 	call	getspl
  2366                              <1> 		; jsr r0,getspl / get the device number in r1
  2367                              <1> 
  2368                              <1> 	;;;
  2369                              <1> 	; 09/05/2022 - Erdogan Tan
  2370                              <1> 	; (I have added [mnti] check because
  2371                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2372                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2373                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2374                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2375 00004FB4 66833D[D6640000]00  <1> 	cmp	word [mnti], 0
  2376 00004FBC 767D                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2377                              <1> 	;;;
  2378                              <1> 
  2379 00004FBE 3A05[D5640000]      <1> 	cmp	al, [mdev]
  2380                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2381 00004FC4 7575                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2382                              <1> 	;jne	error
  2383                              <1>         	; bne errora / no error
  2384 00004FC6 30C0                <1> 	xor	al, al ; ah = 0
  2385                              <1> sysumnt_0: ;1:
  2386                              <1>      	; 11/01/2022
  2387                              <1> 	;cmp 	[sb1+1], al ; 0
  2388                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2389                              <1> 	;		   ; / (inhibit bit set)?
  2390                              <1> 	;jna	short sysumnt_1		
  2391                              <1> 	;	; bne 1b / yes, wait
  2392                              <1> 	;call	idle ; (wait for hardware interrupt)
  2393                              <1> 	;jmp	short sysumnt_0
  2394                              <1> sysumnt_1:        
  2395                              <1> 	; 15/05/2022
  2396                              <1> 	; change user's current directory to mounting directory
  2397                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2398 00004FC8 3805[36650000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2399 00004FCE 7643                <1> 	jna	short sysumnt_4
  2400                              <1> 	;;;
  2401                              <1> 	; 15/05/2022
  2402                              <1> 	; It is needed to change the parent process's current
  2403                              <1> 	; directory because shell runs (/etc/umount) 
  2404                              <1> 	; as child process.
  2405 00004FD0 31DB                <1> 	xor	ebx, ebx 
  2406 00004FD2 8A1D[3B650000]      <1> 	mov	bl, [u.uno]
  2407 00004FD8 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2408 00004FDA 81C3[22620000]      <1> 	add	ebx, p.ppid-2
  2409 00004FE0 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2410 00004FE3 BE[04620000]        <1> 	mov	esi, p.pid
  2411 00004FE8 29C9                <1> 	sub	ecx, ecx
  2412 00004FEA B110                <1> 	mov	cl, nproc ; 16  
  2413                              <1> sysumnt_2:	
  2414 00004FEC 66AD                <1> 	lodsw
  2415 00004FEE 6639D0              <1> 	cmp	ax, dx
  2416 00004FF1 7402                <1> 	je	short sysumnt_3
  2417 00004FF3 E2F7                <1> 	loop	sysumnt_2
  2418                              <1> sysumnt_3:
  2419 00004FF5 31C0                <1> 	xor	eax, eax
  2420 00004FF7 81EE[04620000]      <1> 	sub	esi, p.pid
  2421 00004FFD D1E6                <1> 	shl	esi, 1
  2422 00004FFF 8B9E[70620000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2423                              <1> 	; ebx points to user (u) structure in upage
  2424 00005005 668B15[D6640000]    <1> 	mov	dx, [mnti]
  2425                              <1> 	;mov	[u.cdir], dx
  2426                              <1> 	;mov	[u.cdrv], al ; 0
  2427 0000500C 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2428 00005010 884352              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2429                              <1> 	;;;
  2430                              <1> sysumnt_4: 
  2431 00005013 A2[D5640000]        <1> 	mov	[mdev], al ; 0
  2432                              <1> 	     	; clr mntd / no, clear these
  2433 00005018 66A3[D6640000]      <1>    	mov	[mnti], ax ; 0
  2434                              <1>         	; clr mnti
  2435                              <1> 
  2436                              <1> 	;; 15/05/2022
  2437                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2438                              <1> 	;mov	ax, dx  ; [u.cdir]
  2439                              <1> 	;call	iget
  2440                              <1> 
  2441 0000501E E9C8E0FFFF          <1>         jmp	sysret
  2442                              <1> 		; br sysreta / return
  2443                              <1> 
  2444                              <1> getspl: ; / get device number from a special file name
  2445 00005023 E8AFEFFFFF          <1> 	call	namei
  2446                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2447                              <1> 		       ; ax = 0 -> file not found 	
  2448                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2449                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2450 00005028 7305                <1> 	jnc	short getspl_0
  2451 0000502A E9D4FEFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2452                              <1> getspl_0:
  2453                              <1> 	;jz	error
  2454                              <1> 	;jc	error
  2455                              <1> 		; jsr r0,namei / get the i-number of the special file
  2456                              <1>                 ; br errora / no such file
  2457 0000502F 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2458                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2459                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2460 00005033 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2461                              <1> 	;jc	error
  2462                              <1> 		; ble errora / less than 0?  yes, error
  2463 00005035 6683F805            <1>         cmp	ax, 5 ;
  2464                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2465                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2466                              <1> 	;;ja	error
  2467                              <1> 		; bgt errora / yes, error
  2468                              <1> 	; 11/01/2022
  2469 00005039 760F                <1> 	jna	short getspl_retn
  2470                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2471                              <1> ;iopen_retn:
  2472                              <1> ;	retn
  2473                              <1> 		; rts r0 / return with device number in r1
  2474                              <1> sysmnt_err0:
  2475 0000503B C705[41650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2475 00005043 0000                <1>
  2476 00005045 E981E0FFFF          <1> 	jmp	error
  2477                              <1> 
  2478                              <1> getspl_retn:
  2479                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2480                              <1> 	; 11/01/2022
  2481                              <1> iopen_retn:
  2482 0000504A C3                  <1> 	retn
  2483                              <1> 
  2484                              <1> iopen:	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2485                              <1> 	;		(Printer initialization)
  2486                              <1> 	; 11/01/2022
  2487                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2488                              <1> 	; 19/05/2015
  2489                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2490                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2491                              <1> 	;
  2492                              <1> 	; open file whose i-number is in r1
  2493                              <1> 	; 
  2494                              <1> 	; INPUTS ->
  2495                              <1> 	;    r1 - inode number
  2496                              <1> 	; OUTPUTS ->
  2497                              <1> 	;    file's inode in core	
  2498                              <1> 	;    r1 - inode number (positive)
  2499                              <1> 	;
  2500                              <1> 	; ((AX = R1))
  2501                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2502                              <1> 	;        
  2503                              <1> ; / open file whose i-number is in r1
  2504 0000504B F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2505                              <1> 		; tst r1 / write or read access?
  2506 0000504E 7568                <1>         jnz	short iopen_2
  2507                              <1> 		; blt 2f / write, go to 2f
  2508 00005050 B202                <1> 	mov	dl, 2 ; read access
  2509 00005052 E864F8FFFF          <1> 	call	access
  2510                              <1>         	; jsr r0,access; 2 
  2511                              <1> 	; / get inode into core with read access
  2512                              <1> 	; DL=2
  2513                              <1> iopen_0:
  2514 00005057 6683F828            <1>         cmp	ax, 40
  2515                              <1> 		; cmp r1,$40. / is it a special file
  2516 0000505B 77ED                <1>         ja	short iopen_retn
  2517                              <1> 		; bgt  3f / no. 3f
  2518 0000505D 50                  <1> 	push	eax ; 08/01/2022
  2519                              <1> 	;push	ax
  2520                              <1> 		; mov r1,-(sp) / yes, figure out
  2521 0000505E 0FB6D8              <1> 	movzx	ebx, al
  2522 00005061 C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2523                              <1> 	;shl	bx, 2
  2524                              <1> 		; asl r1
  2525 00005064 81C3[68500000]      <1>         add     ebx, iopen_1 - 4
  2526 0000506A FF23                <1> 	jmp	dword [ebx]
  2527                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2528                              <1> iopen_1: ; 1:
  2529 0000506C [D0500000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2530                              <1>  		 ;otty / tty ; r1=2
  2531                              <1>         	 ;oppt / ppt ; r1=4
  2532 00005070 [88510000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2533                              <1> 		 ;sret / mem ; r1=6
  2534                              <1> 		 ;sret / rf0
  2535                              <1>         	 ;sret / rk0
  2536                              <1>         	 ;sret / tap0
  2537                              <1>         	 ;sret / tap1
  2538                              <1>         	 ;sret / tap2
  2539                              <1>         	 ;sret / tap3
  2540                              <1>         	 ;sret / tap4
  2541                              <1>         	 ;sret / tap5
  2542                              <1>         	 ;sret / tap6
  2543                              <1>         	 ;sret / tap7
  2544 00005074 [88510000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2545 00005078 [88510000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2546 0000507C [88510000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2547 00005080 [88510000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2548 00005084 [88510000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2549 00005088 [88510000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2550                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2551                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2552                              <1> 	; 13/06/2022 - (lpt_init)
  2553 0000508C [54520000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2554 00005090 [E1500000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2555                              <1> 		 ;ocvt / tty0
  2556 00005094 [E1500000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2557                              <1> 		 ;ocvt / tty1
  2558 00005098 [E1500000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2559                              <1> 		 ;ocvt / tty2
  2560 0000509C [E1500000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2561                              <1> 		 ;ocvt / tty3
  2562 000050A0 [E1500000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2563                              <1> 		 ;ocvt / tty4
  2564 000050A4 [E1500000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2565                              <1> 		 ;ocvt / tty5
  2566 000050A8 [E1500000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2567                              <1> 		 ;ocvt / tty6
  2568 000050AC [E1500000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2569                              <1> 		 ;ocvt / tty7
  2570 000050B0 [E1500000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2571                              <1> 		 ;error / crd
  2572 000050B4 [E1500000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2573                              <1> 
  2574                              <1> iopen_2: ; 2: / check open write access
  2575 000050B8 66F7D8              <1> 	neg	ax
  2576                              <1> 		;neg r1 / make inode number positive
  2577 000050BB B201                <1> 	mov	dl, 1 ; write access
  2578 000050BD E8F9F7FFFF          <1> 	call	access
  2579                              <1> 		;jsr r0,access; 1 / get inode in core
  2580                              <1> 	; DL=1
  2581                              <1> 	; 11/01/2022
  2582 000050C2 F605[E5610000]40    <1> 	test	byte [i.flgs+1], 40h
  2583                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2584                              <1>  		; bit $40000,i.flgs / is it a directory?
  2585 000050C9 748C                <1> 	jz	short iopen_0
  2586                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2587                              <1> 	;jmp	error ; permission denied !
  2588 000050CB E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2589                              <1> 	;;jnz	error		
  2590                              <1>        		; bne 2f / yes, transfer (error)
  2591                              <1>         ;;jmp	short iopen_0
  2592                              <1> 	;cmp	ax, 40
  2593                              <1> 		; cmp r1,$40. / no, is it a special file?
  2594                              <1>         ;ja	short iopen_2
  2595                              <1> 		; bgt 3f / no, return
  2596                              <1> 	;push	ax
  2597                              <1> 		; mov r1,-(sp) / yes
  2598                              <1> 	;movzx	ebx, al
  2599                              <1> 	;shl	bx, 1
  2600                              <1> 		; asl r1
  2601                              <1> 	;add	ebx, ipen_3 - 2
  2602                              <1> 	;jmp	dword [ebx]
  2603                              <1> 		; jmp *1f-2(r1) / figure out 
  2604                              <1> 			; / which special file it is and transfer
  2605                              <1> ;iopen_3: ; 1:
  2606                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2607                              <1>  		 ;otty / tty ; r1=2
  2608                              <1>         	 ;leadr / ppt ; r1=4
  2609                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2610                              <1> 		 ;sret / mem ; r1=6
  2611                              <1> 		 ;sret / rf0
  2612                              <1>         	 ;sret / rk0
  2613                              <1>         	 ;sret / tap0
  2614                              <1>         	 ;sret / tap1
  2615                              <1>         	 ;sret / tap2
  2616                              <1>         	 ;sret / tap3
  2617                              <1>         	 ;sret / tap4
  2618                              <1>         	 ;sret / tap5
  2619                              <1>         	 ;sret / tap6
  2620                              <1>         	 ;sret / tap7
  2621                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2622                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2623                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2624                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2625                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2626                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2627                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2628                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2629                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2630                              <1> 		 ;ocvt / tty0
  2631                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2632                              <1> 		 ;ocvt / tty1
  2633                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2634                              <1> 		 ;ocvt / tty2
  2635                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2636                              <1> 		 ;ocvt / tty3
  2637                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2638                              <1> 		 ;ocvt / tty4
  2639                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2640                              <1> 		 ;ocvt / tty5
  2641                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2642                              <1> 		 ;ocvt / tty6
  2643                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2644                              <1> 		 ;ocvt / tty7
  2645                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2646                              <1> 		 ;/ ejec / lpr
  2647                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2648                              <1> 
  2649                              <1> otty: ;/ open console tty for reading or writing
  2650                              <1> 	; 03/03/2022
  2651                              <1> 	; 02/03/2022
  2652                              <1> 	; 26/02/2022
  2653                              <1> 	; 09/02/2022
  2654                              <1> 	; 06/02/2022
  2655                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2656                              <1> 	; 16/11/2015
  2657                              <1> 	; 12/11/2015
  2658                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2659                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2660                              <1> 	; 16/07/2013
  2661                              <1> 	; Retro UNIX 8086 v1 modification:
  2662                              <1> 	;  If a tty is open for read or write by
  2663                              <1> 	;     a process (u.uno), only same process can open
  2664                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2665                              <1> 	;
  2666                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2667                              <1> 	;
  2668 000050D0 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2669 000050D7 8A83[43620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2670                              <1> 	; 13/01/2014
  2671                              <1> 	;jmp	short ottyp
  2672                              <1> 	; 26/02/2022
  2673 000050DD 88C4                <1> 	mov	ah, al
  2674 000050DF EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2675                              <1> ocvt:
  2676 000050E1 2C0A                <1> 	sub	al, 10
  2677                              <1> ;ottyp:	; (call from sysstty)
  2678                              <1> 	; 08/01/2022
  2679 000050E3 31DB                <1> 	xor	ebx, ebx
  2680                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2681                              <1> 	; 26/02/2022
  2682 000050E5 B4FF                <1> 	mov	ah, 0FFh
  2683                              <1> ottypc:
  2684                              <1> 	; 03/03/2022
  2685                              <1> 	; 26/02/2022
  2686                              <1> 	; 09/02/2022
  2687                              <1> 	; 08/01/2022
  2688                              <1> 	; 16/11/2015
  2689                              <1> 	; 12/11/2015
  2690                              <1> 	; 18/05/2015 (32 bit modifications)
  2691                              <1> 	; 06/12/2013 - 13/07/2014
  2692 000050E7 88C6                <1> 	mov	dh, al ; tty number
  2693                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2694                              <1> 	; 08/01/2022
  2695 000050E9 88C3                <1> 	mov	bl, al
  2696 000050EB D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2697                              <1> 	; 26/01/2014	
  2698 000050ED 81C3[74610000]      <1> 	add 	ebx, ttyl
  2699 000050F3 668B0B              <1> 	mov 	cx, [ebx]
  2700                              <1> 		   ; CL = lock value (0 or process number)
  2701                              <1> 		   ; CH = open count 
  2702 000050F6 20C9                <1> 	and 	cl, cl
  2703                              <1> 	; 13/01/2014
  2704                              <1> 	;jz 	short otty_ret
  2705                              <1> 	; 08/01/2022
  2706 000050F8 7447                <1> 	jz 	short ottys_0
  2707                              <1> 	;
  2708                              <1> 	; 16/11/2015
  2709 000050FA 3A0D[3B650000]      <1> 	cmp 	cl, [u.uno]
  2710 00005100 746E                <1> 	je	short ottys_3
  2711                              <1> 	;
  2712                              <1> 	;
  2713                              <1> 	; 26/02/2022
  2714                              <1> 	; (is it the console tty of the current process?)
  2715                              <1> 	; ((fast check/permit for console tty open function))
  2716 00005102 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2717 00005104 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2718                              <1> 	;
  2719                              <1> 	; 26/02/2022
  2720                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2721                              <1> 	;shl 	bl, 1
  2722                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2723                              <1> 	;;movzx ebx, byte [u.uno]
  2724                              <1> 	;mov	bl, [u.uno]
  2725                              <1> 	;shl 	bl, 1
  2726                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2727                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2728                              <1> 	; 26/02/2022 (BugFix) ; *
  2729 00005106 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2730 00005109 D1E6                <1> 	shl 	esi, 1
  2731 0000510B 668B86[02620000]    <1> 	mov 	ax, [esi+p.pid-2]
  2732 00005112 96                  <1> 	xchg	esi, eax
  2733 00005113 A0[3B650000]        <1> 	mov	al, [u.uno]
  2734 00005118 D0E0                <1> 	shl 	al, 1
  2735 0000511A 663BB0[22620000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2736 00005121 744D                <1> 	je 	short ottys_3 ; *
  2737                              <1> 	; 26/02/2022
  2738                              <1> 	; check console tty of the process
  2739                              <1> 	; (open permission must be given if the -requested- tty is
  2740                              <1> 	;  console tty of current process)
  2741 00005123 D0E8                <1> 	shr	al, 1
  2742 00005125 38B0[43620000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2743 0000512B 7443                <1> 	je 	short ottys_3
  2744                              <1> 	;
  2745                              <1> 	; the tty is locked by another process
  2746                              <1> 	; except the parent process (p.ppid)
  2747                              <1>         ;
  2748                              <1> 	; 09/02/2022
  2749                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2750                              <1> 	;		; permission denied ! error
  2751                              <1> otty_err: ; 13/01/2014
  2752                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2753                              <1> 	;;jnz	error
  2754                              <1> 	; 05/12/2021
  2755                              <1> 	;jz	short otty_stc_retn
  2756                              <1> 	;jmp	error
  2757                              <1> 	; 09/02/2022
  2758 0000512D 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2759 00005130 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2760                              <1> 	; iopen (dl=1 or dl=2)
  2761 00005132 C705[41650000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2761 0000513A 0000                <1>
  2762                              <1> 			; permission denied ! error
  2763 0000513C E98ADFFFFF          <1> 	jmp	error
  2764                              <1> ;otty_stc_retn:
  2765                              <1> 	;stc
  2766                              <1> 	;retn
  2767                              <1> ottys_0:
  2768                              <1> 	; 08/01/2022
  2769                              <1> otty_ret: 
  2770                              <1> 	; 13/01/2014
  2771 00005141 80FE07              <1> 	cmp 	dh, 7
  2772 00005144 7624                <1> 	jna	short ottys_2
  2773                              <1> 	; 16/11/2015
  2774                              <1> com_port_check:
  2775 00005146 BE[92610000]        <1> 	mov	esi, com1p
  2776 0000514B 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2777 0000514E 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2778 00005150 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2779                              <1> ottys_1:
  2780                              <1> 	; 12/11/2015
  2781 00005151 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2782 00005154 7714                <1> 	ja	short com_port_ready
  2783                              <1> 	;
  2784                              <1> 	; 09/02/2022
  2785 00005156 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2786 00005159 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2787 0000515B C705[41650000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2787 00005163 0000                <1>
  2788                              <1> 			   ; device not ready ! error
  2789                              <1> 	;jmp	short otty_err
  2790 00005165 E961DFFFFF          <1> 	jmp	error
  2791                              <1> com_port_ready:
  2792                              <1> ottys_2:
  2793                              <1> 	; 02/03/2022
  2794                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2795                              <1> 	;jnz	short ottys_3
  2796 0000516A 8A0D[3B650000]      <1> 	mov	cl, [u.uno]
  2797                              <1> ottys_3:
  2798 00005170 FEC5                <1> 	inc 	ch
  2799 00005172 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2800                              <1> 	; 06/12/2013
  2801 00005175 FEC6                <1> 	inc	dh ; tty number + 1
  2802 00005177 BB[1C650000]        <1> 	mov	ebx, u.ttyp
  2803                              <1> 	; 13/01/2014
  2804 0000517C F6C202              <1> 	test	dl, 2 ; open for read sign
  2805 0000517F 7501                <1> 	jnz	short ottys_4
  2806 00005181 43                  <1> 	inc	ebx
  2807                              <1> ottys_4:
  2808                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2809 00005182 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2810                              <1> 	; 09/02/2022
  2811 00005184 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2812 00005186 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2813                              <1> sret:
  2814                              <1> 	;pop 	ax
  2815 00005188 58                  <1> 	pop	eax ; 08/01/2022
  2816                              <1> otty_retn:	; 09/02/2022
  2817                              <1> iclose_retn:	
  2818 00005189 C3                  <1> 	retn
  2819                              <1> 
  2820                              <1> 	;
  2821                              <1> 	; Original UNIX v1 'otty' routine:
  2822                              <1> 	;	
  2823                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2824                              <1>         ;                 / reader status reg
  2825                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2826                              <1>         ;                 / punch status reg
  2827                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2828                              <1>         ;                          / console tty buffer
  2829                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2830                              <1>         ;            / console tty
  2831                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2832                              <1>         ;             / buffer header
  2833                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2834                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2835                              <1>         ;                 / tty
  2836                              <1>         ;br     sret / ?
  2837                              <1> ;sret:
  2838                              <1> 		;clr *$ps / set processor priority to zero
  2839                              <1> ;	pop	ax
  2840                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2841                              <1> ;3:
  2842                              <1> ;	retn
  2843                              <1>         	;rts r0
  2844                              <1> 	
  2845                              <1> ;ocvt:	; < open tty >
  2846                              <1> 	; 13/01/2014
  2847                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2848                              <1> 	; 24/09/2013 consistency check -> ok
  2849                              <1> 	; 16/09/2013
  2850                              <1> 	; 03/09/2013
  2851                              <1> 	; 27/08/2013
  2852                              <1> 	; 16/08/2013
  2853                              <1> 	; 16/07/2013
  2854                              <1> 	; 27/05/2013
  2855                              <1> 	; 21/05/2013
  2856                              <1> 	;
  2857                              <1> 	; Retro UNIX 8086 v1 modification !
  2858                              <1> 	; 
  2859                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2860                              <1> 	;	(exactly different than this one)
  2861                              <1> 	;	was in 'u9.s' file.
  2862                              <1> 	;
  2863                              <1> 	; 16/07/2013
  2864                              <1> 	; Retro UNIX 8086 v1 modification:
  2865                              <1> 	;  If a tty is open for read or write by
  2866                              <1> 	;     a process (u.uno), only same process can open
  2867                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2868                              <1> 	;
  2869                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2870                              <1> 
  2871                              <1> 	; 16/09/2013
  2872                              <1> 	; sub 	al, 10
  2873                              <1> 	
  2874                              <1> 	; 06/12/2013
  2875                              <1> 	;cmp	al, 7
  2876                              <1>         ;jna     short ottyp
  2877                              <1> 	; 13/01/2014
  2878                              <1> 	;jmp	short ottyp
  2879                              <1> 
  2880                              <1> ;oppt: / open paper tape for reading or writing
  2881                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2882                              <1> ;        tstb   pptiflg / is file already open
  2883                              <1> ;        bne    2f / yes, branch
  2884                              <1> ;1:
  2885                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2886                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2887                              <1> ;               br .+4 / for paper tape input and place in free list
  2888                              <1> ;        br     1b
  2889                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2890                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2891                              <1> ;        br     sret
  2892                              <1> ;2:
  2893                              <1> ;        jmp    error / file already open
  2894                              <1> 
  2895                              <1> iclose:
  2896                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2897                              <1> 	; 19/05/2015
  2898                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2899                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2900                              <1> 	;
  2901                              <1> 	; close file whose i-number is in r1
  2902                              <1> 	; 
  2903                              <1> 	; INPUTS ->
  2904                              <1> 	;    r1 - inode number
  2905                              <1> 	; OUTPUTS ->
  2906                              <1> 	;    file's inode in core	
  2907                              <1> 	;    r1 - inode number (positive)
  2908                              <1> 	;
  2909                              <1> 	; ((AX = R1))
  2910                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2911                              <1> 	;        
  2912                              <1> ;/ close file whose i-number is in r1
  2913 0000518A B202                <1> 	mov	dl, 2 ; 12/01/2014
  2914 0000518C F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2915                              <1> 		; tst r1 / test i-number
  2916                              <1>         ;jnz	short iclose_2
  2917                              <1> 		; blt 2f / if neg., branch
  2918 0000518F 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2919                              <1> 	; 16/07/2013 
  2920 00005191 66F7D8              <1> 	neg	ax ; make it positive
  2921                              <1> 	; 12/01/2014
  2922 00005194 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2923                              <1> iclose_0:
  2924 00005196 6683F828            <1> 	cmp	ax, 40
  2925                              <1> 		; cmp r1,$40. / is it a special file
  2926 0000519A 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2927                              <1> 		; bgt 3b / no, return
  2928                              <1> 	; 12/01/2014
  2929                              <1> 	; DL=2 -> special file was opened for reading
  2930                              <1> 	; DL=1 -> special file was opened for writing
  2931 0000519C 50                  <1> 	push	eax ; 08/01/2022
  2932                              <1> 	;push	ax
  2933                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2934 0000519D 0FB6D8              <1> 	movzx	ebx, al
  2935                              <1> 	; 08/01/2022
  2936 000051A0 C0E302              <1> 	shl	bl, 2
  2937                              <1> 	;shl	bx, 2
  2938                              <1> 		; asl r1
  2939 000051A3 81C3[A7510000]      <1> 	add	ebx, iclose_1 - 4
  2940 000051A9 FF23                <1> 	jmp	dword [ebx]
  2941                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2942                              <1> iclose_1 :
  2943 000051AB [F7510000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2944 000051AF [52520000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2945 000051B3 [52520000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2946 000051B7 [52520000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2947 000051BB [52520000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2948 000051BF [52520000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2949 000051C3 [52520000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2950 000051C7 [52520000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2951 000051CB [52520000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2952                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2953                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2954 000051CF [06520000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2955 000051D3 [06520000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2956 000051D7 [06520000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2957 000051DB [06520000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2958 000051DF [06520000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2959 000051E3 [06520000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2960 000051E7 [06520000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2961 000051EB [06520000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2962 000051EF [06520000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2963 000051F3 [06520000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2964                              <1> 
  2965                              <1> 	; 1:
  2966                              <1> 	;        ctty   / tty
  2967                              <1> 	;        cppt   / ppt
  2968                              <1> 	;        sret   / mem
  2969                              <1> 	;        sret   / rf0
  2970                              <1> 	;        sret   / rk0
  2971                              <1> 	;        sret   / tap0
  2972                              <1> 	;        sret   / tap1
  2973                              <1> 	;        sret   / tap2
  2974                              <1> 	;        sret   / tap3
  2975                              <1> 	;        sret   / tap4
  2976                              <1> 	;        sret   / tap5
  2977                              <1> 	;        sret   / tap6
  2978                              <1> 	;        sret   / tap7
  2979                              <1> 	;        ccvt   / tty0
  2980                              <1> 	;        ccvt   / tty1
  2981                              <1> 	;        ccvt   / tty2
  2982                              <1> 	;        ccvt   / tty3
  2983                              <1> 	;        ccvt   / tty4
  2984                              <1> 	;        ccvt   / tty5
  2985                              <1> 	;        ccvt   / tty6
  2986                              <1> 	;        ccvt   / tty7
  2987                              <1> 	;        error / crd
  2988                              <1> 
  2989                              <1> ;iclose_2: ; 2: / negative i-number
  2990                              <1> 	;neg	ax
  2991                              <1> 		;neg r1 / make it positive
  2992                              <1> 	;cmp	ax, 40
  2993                              <1> 		;cmp r1,$40. / is it a special file?
  2994                              <1>         ;ja	short @b
  2995                              <1> 		;bgt    3b / no. return
  2996                              <1> 	;push	ax
  2997                              <1> 		;mov r1,-(sp)
  2998                              <1> 	;movzx	ebx, al
  2999                              <1> 	;shl	bx, 1
  3000                              <1> 		;asl r1 / yes. compute jump address and transfer
  3001                              <1> 	;add	ebx, iclose_3 - 2
  3002                              <1> 	;jmp	dword [ebx]
  3003                              <1> 		;jmp *1f-2(r1) / figure out 
  3004                              <1> ;iclose_3:
  3005                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  3006                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  3007                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  3008                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  3009                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  3010                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  3011                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3012                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3013                              <1> 	 ;dd	sret ; lpr, AX = 9	
  3014                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3015                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3016                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3017                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3018                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3019                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3020                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3021                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3022                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3023                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3024                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3025                              <1> 	
  3026                              <1> 	;1:
  3027                              <1> 	;      	ctty   / tty
  3028                              <1> 	;       leadr  / ppt
  3029                              <1> 	;       sret   / mem
  3030                              <1> 	;       sret   / rf0
  3031                              <1> 	;       sret   / rk0
  3032                              <1> 	;       sret   / tap0
  3033                              <1> 	;       sret   / tap1
  3034                              <1> 	;       sret   / tap2
  3035                              <1> 	;       sret   / tap3
  3036                              <1> 	;       sret   / tap4
  3037                              <1> 	;       sret   / tap5
  3038                              <1> 	;       sret   / tap6
  3039                              <1> 	;       sret   / tap7
  3040                              <1> 	;       ccvt   / tty0
  3041                              <1> 	;       ccvt   / tty1
  3042                              <1> 	;       ccvt   / tty2
  3043                              <1> 	;       ccvt   / tty3
  3044                              <1> 	;       ccvt   / tty4
  3045                              <1> 	;       ccvt   / tty5
  3046                              <1> 	;       ccvt   / tty6
  3047                              <1> 	;       ccvt   / tty7
  3048                              <1> 	;/      ejec   / lpr
  3049                              <1> 
  3050                              <1> ctty: ; / close console tty
  3051                              <1> 	; 26/02/2022
  3052                              <1> 	; 09/02/2022
  3053                              <1> 	; 06/02/2022
  3054                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3055                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3056                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3057                              <1> 	;
  3058                              <1> 	; Retro UNIX 8086 v1 modification !
  3059                              <1> 	; (DL = 2 -> it is open for reading)
  3060                              <1> 	; (DL = 1 -> it is open for writing)
  3061                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3062                              <1> 	;
  3063                              <1> 	; 06/12/2013
  3064 000051F7 0FB61D[3B650000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3065 000051FE 8A83[43620000]      <1>         mov     al, [ebx+p.ttyc-1]
  3066                              <1> 	; 13/01/2014
  3067                              <1> 	;jmp	short cttyp
  3068                              <1> 	; 06/02/2022
  3069 00005204 EB04                <1> 	jmp	short ctty_0
  3070                              <1> ccvt:
  3071 00005206 2C0A                <1> 	sub 	al, 10
  3072                              <1> cttyp:	; (call from sysstty)
  3073                              <1> 	; 08/01/2022
  3074 00005208 31DB                <1> 	xor	ebx, ebx
  3075                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  3076                              <1> 	; 08/01/2022
  3077                              <1> 	; 18/05/2015 (32 bit modifications)
  3078                              <1> 	; 16/08/2013 - 26/01/2014
  3079                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3080                              <1> 	; 08/01/2022
  3081 0000520A 88C3                <1> 	mov	bl, al
  3082 0000520C D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3083                              <1> 	; 26/01/2014
  3084 0000520E 81C3[74610000]      <1> 	add 	ebx, ttyl
  3085 00005214 88C6                <1> 	mov 	dh, al ; tty number
  3086 00005216 668B03              <1> 	mov 	ax, [ebx]
  3087                              <1> 		   ; AL = lock value (0 or process number)
  3088                              <1> 		   ; AH = open count 
  3089 00005219 20E4                <1> 	and 	ah, ah
  3090 0000521B 7514                <1> 	jnz	short ctty_ret
  3091                              <1>   	; 09/02/2022
  3092 0000521D 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3093 00005220 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3094                              <1> 	; iclose (dl=1 or dl=2)
  3095 00005222 C705[41650000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3095 0000522A 0000                <1>
  3096                              <1> 			; device not open ! error
  3097                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3098 0000522C E99ADEFFFF          <1> 	jmp	error
  3099                              <1> 	; 26/01/2014
  3100                              <1> ctty_ret:
  3101 00005231 FECC                <1> 	dec 	ah ; decrease open count
  3102 00005233 7502                <1> 	jnz	short ctty_1
  3103 00005235 30C0                <1> 	xor	al, al ; unlock/free tty
  3104                              <1> ctty_1:
  3105 00005237 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3106                              <1> 	;
  3107 0000523A BB[1C650000]        <1> 	mov	ebx, u.ttyp
  3108                              <1> 	;test	dl, 1 ; open for write sign
  3109                              <1> 	;jz	short ctty_2
  3110                              <1> 	; 26/02/2022
  3111 0000523F F6C202              <1> 	test	dl, 2 ; open for read sign
  3112 00005242 7501                <1> 	jnz	short ctty_2
  3113 00005244 43                  <1> 	inc	ebx
  3114                              <1> ctty_2:
  3115 00005245 FEC6                <1> 	inc	dh ; tty number + 1
  3116 00005247 3A33                <1> 	cmp	dh, [ebx]
  3117                              <1> 	;jne	short cret
  3118 00005249 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3119                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3120 0000524B C60300              <1> 	mov	byte [ebx], 0
  3121                              <1> ctty_3:
  3122                              <1> 	; 09/02/2022
  3123 0000524E 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3124 00005250 7401                <1> 	jz	short ctty_4
  3125                              <1> cret:
  3126                              <1> 	;pop	ax
  3127                              <1> 	; 08/01/2022
  3128 00005252 58                  <1> 	pop	eax
  3129                              <1> ctty_stc_retn:	; 09/02/2022
  3130                              <1> ctty_4:
  3131 00005253 C3                  <1> 	retn
  3132                              <1> 
  3133                              <1> ;ctty_err: ; 13/01/2014
  3134                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3135                              <1> ;	jnz	error
  3136                              <1> ;	stc
  3137                              <1> ;	retn
  3138                              <1> 
  3139                              <1> 	; Original UNIX v1 'ctty' routine:
  3140                              <1> 	;	
  3141                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3142                              <1> 	;		;/ point r5 to the console tty buffer
  3143                              <1>         ;decb   (r5) / dec number of processes using console tty
  3144                              <1>         ;br     sret / return via sret
  3145                              <1> 
  3146                              <1> ;ccvt:	; < close tty >
  3147                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3148                              <1> 	;
  3149                              <1> 	; Retro UNIX 8086 v1 modification !
  3150                              <1> 	; 
  3151                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3152                              <1> 	;		(exactly different than this one)
  3153                              <1> 	;	was in 'u9.s' file.
  3154                              <1> 	;
  3155                              <1> 	; DL = 2 -> it is open for reading
  3156                              <1> 	; DL = 1 -> it is open for writing
  3157                              <1> 	;
  3158                              <1> 	; 17/09/2013
  3159                              <1> 	;sub 	al, 10
  3160                              <1> 	;cmp	al, 7
  3161                              <1> 	;jna	short cttyp
  3162                              <1> 	; 13/01/2014
  3163                              <1> 	;jmp	short cttyp
  3164                              <1> 
  3165                              <1> ;cppt: / close paper tape
  3166                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3167                              <1> ;1:
  3168                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3169                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3170                              <1> ;                          / and assign to free list
  3171                              <1> ;               br sret
  3172                              <1> ;        br     1b
  3173                              <1> 
  3174                              <1> ;ejec:	
  3175                              <1> ;	jmp	error
  3176                              <1> ;/ejec:
  3177                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3178                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3179                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3180                              <1> ;/       br     sret / return to caller via 'sret'
  3181                              <1> 
  3182                              <1> ejec:
  3183                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  3184                              <1> 	;	     - Printer Initialization
  3185                              <1> lpt_init:	
  3186                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3187                              <1> 	;
  3188                              <1> 	; Default printer port: 378h ; LPT1
  3189                              <1> 	
  3190 00005254 B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3191                              <1> 	;call	int17h
  3192 00005256 E8BDFAFFFF          <1> 	call	PRNOP
  3193 0000525B 7414                <1> 	jz	short lpt_init_ok
  3194                              <1> 	
  3195                              <1> 	; replace error code with 'device not ready' error
  3196                              <1> 	; (this may be better for 'sysopen')
  3197 0000525D B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3198 00005262 A3[41650000]        <1> 	mov	[u.error], eax
  3199                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3200 00005267 A3[EC640000]        <1> 	mov	[u.r0], eax
  3201 0000526C E95ADEFFFF          <1> 	jmp	error ; (better)	
  3202                              <1> 	
  3203                              <1> lpt_init_ok:
  3204                              <1> 	;jmp	short cret
  3205 00005271 58                  <1> 	pop	eax    ; inode number
  3206 00005272 C3                  <1> 	retn
  3207                              <1> 	
  2121                                  %include 'u8.s'        ; 11/06/2015
  2122                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS8.INC
  2123                              <1> ; Last Modification: 19/07/2022
  2124                              <1> ; ----------------------------------------------------------------------------
  2125                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2126                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2127                              <1> ;
  2128                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2129                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2130                              <1> ; <Bell Laboratories (17/3/1972)>
  2131                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2132                              <1> ;
  2133                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2134                              <1> ;
  2135                              <1> ; ****************************************************************************
  2136                              <1> 
  2137                              <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2138                              <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2139                              <1> ;---------------------------------------------------------------------
  2140                              <1> ; Buffer Header: -8 bytes-
  2141                              <1> ; word 1 - byte 0 - device (disk index) number (0 to 5)
  2142                              <1> ;	   byte 1 - status bits
  2143                              <1> ;	 	bit 0 - valid buffer bit (1 = valid, 0 = invalid, new)
  2144                              <1> ;		bit 1 - write bit (also modified bit)
  2145                              <1> ;		bit 2 - read bit	
  2146                              <1> ;		bit 3 to bit 7 are not used
  2147                              <1> ; word 2 - byte & byte 3 not used
  2148                              <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7:
  2149                              <1> ;		physical block/sector address (32 bit LBA)
  2150                              <1> ;---------------------------------------------------------------------
  2151                              <1> 
  2152                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2153                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2154                              <1> ;; Word 1, byte 0 = device id
  2155                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2156                              <1> ;;          bit 9 = write bit
  2157                              <1> ;;	    bit 10 = read bit	  
  2158                              <1> ;;	    bit 12 = waiting to write bit	
  2159                              <1> ;;	    bit 13 = waiting to read bit
  2160                              <1> ;;	    bit 15 = inhibit bit
  2161                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2162                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2163                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2164                              <1> ;;
  2165                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2166                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2167                              <1> ;;
  2168                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2169                              <1> ;; Word 1, Byte 0 = device id
  2170                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2171                              <1> ;;          bit 9 = write bit
  2172                              <1> ;;	    bit 10 = read bit	  
  2173                              <1> ;;	    bit 12 = waiting to write bit	
  2174                              <1> ;;	    bit 13 = waiting to read bit
  2175                              <1> ;;	    bit 15 = inhibit bit
  2176                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2177                              <1> ;;
  2178                              <1> ;; Original UNIX v1 ->
  2179                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2180                              <1> ;; Original UNIX v1 -> 
  2181                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2182                              <1> ;;
  2183                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2184                              <1> ;;
  2185                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2186                              <1> ;;          0 = fd0
  2187                              <1> ;;	    1 = fd1
  2188                              <1> ;;	    2 = hd0
  2189                              <1> ;;	    3 = hd1
  2190                              <1> ;;	    4 = hd2
  2191                              <1> ;;	    5 = hd3
  2192                              <1> 
  2193                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2194                              <1> 
  2195                              <1> 	; 08/02/2022
  2196                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2197                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2198                              <1> 	; 26/04/2013
  2199                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2200                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2201                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2202                              <1> 
  2203                              <1> 	; 08/02/2022
  2204                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2205                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2206                              <1> 	; 26/04/2013
  2207                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2208                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2209                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2210                              <1> 
  2211                              <1> bread: 
  2212                              <1> 	; 19/07/2022
  2213                              <1> 	; 15/07/2022
  2214                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2215                              <1> 	; 08/02/2022
  2216                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2217                              <1> 	; 14/07/2015
  2218                              <1> 	; 10/07/2015
  2219                              <1> 	; 09/06/2015
  2220                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2221                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2222                              <1> 	;	
  2223                              <1> 	; / read a block from a block structured device
  2224                              <1> 	;
  2225                              <1> 	; INPUTS ->
  2226                              <1> 	;    [u.fofp] points to the block number
  2227                              <1> 	;    ECX = maximum block number allowed on device
  2228                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2229                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2230                              <1> 	;    [u.count]	number of bytes to read in
  2231                              <1> 	; OUTPUTS ->
  2232                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2233                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2234                              <1> 	;
  2235                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX, ESI, EDI))
  2236                              <1> 	;
  2237                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2238                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2239                              <1> 	;	is increased by 1. For example: If user/program request 
  2240                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2241                              <1> 	;  	the next block number just as 512 byte reading is done.
  2242                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2243                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2244                              <1> 	;       enough to keep byte position/offset of the disk), this
  2245                              <1> 	;	defect will not be corrected, user/program must request
  2246                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2247                              <1> 	;       for achieving correct result. In future version(s), 
  2248                              <1> 	;	this defect will be corrected by using different 
  2249                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2250                              <1> 
  2251                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2252                              <1> 			       ; / (only works on tape)
  2253                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2254                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2255                              <1> ;1:
  2256                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2257                              <1> 			    ; / maximum block # allowed on device
  2258                              <1> 		; jnb short @f
  2259                              <1> 		; bhis	1f / yes, 1f (error)
  2260                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2261                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2262                              <1> 		; mov (sp)+,r1 / return block # to r1
  2263                              <1> 		; inc r1 / bump block # to next consecutive block
  2264                              <1> 		; dec (sp) / "2-1-cold" on stack
  2265                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2266                              <1> ;1:
  2267                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2268                              <1> 	;push	ecx ; **
  2269                              <1> 	; 26/04/2013
  2270                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2271 00005273 2C03                <1> 	sub	al, 3
  2272                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2273 00005275 A2[54650000]        <1> 	mov	[u.brwdev], al
  2274                              <1> 	; 09/06/2015
  2275                              <1> 	;movzx	ebx, al
  2276                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2277                              <1> 	; 12/01/2022 (BugFix)
  2278 0000527A C0E002              <1> 	shl	al, 2 ; * 4
  2279 0000527D 8B88[525C0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2280                              <1> bread_0:
  2281 00005283 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2282                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2283                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2284 00005284 8B1D[FC640000]      <1> 	mov	ebx, [u.fofp]
  2285 0000528A 8B03                <1> 	mov	eax, [ebx]
  2286 0000528C C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2287                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2288                              <1> 			       ; / block #
  2289 0000528F 39C8                <1> 	cmp	eax, ecx
  2290                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2291                              <1>        	                     ; / block number allowed
  2292                              <1> 	;jnb	error 	     ; 18/04/2013
  2293                              <1> 		; bhis error10 / yes, error
  2294                              <1> 	; 08/02/2022
  2295                              <1> 	;jb	short bread_1
  2296                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2297                              <1> 	;jmp	error
  2298 00005291 7346                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2299                              <1> bread_1:
  2300                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2301                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2302                              <1> 	; EAX = Block number (zero based)
  2303                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2304                              <1> preread: ;; call preread
  2305 00005293 BF[54650000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2306 00005298 E8DC010000          <1> 	call	bufaloc_0 ; 26/04/2013
  2307                              <1> 	;; jc 	error
  2308                              <1> 	; EBX = Buffer (Header) Address -Physical-
  2309                              <1>         ; EAX = Block/Sector number (r1)
  2310                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2311                              <1> 	; 14/03/2013
  2312 0000529D 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2313                              <1>        		; br 1f / branch if block already in a I/O buffer
  2314 0000529F 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2315                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2316 000052A4 E8A8010000          <1> 	call	poke
  2317                              <1>         	; jsr r0,poke / perform the read
  2318                              <1> 	;;jc	error ;2 0/07/2013
  2319                              <1> ; 1:
  2320                              <1>  		; clr *$ps / ps = 0
  2321                              <1>         	; rts r0
  2322                              <1> 	; 08/02/2022
  2323 000052A9 7305                <1> 	jnc	short bread_2
  2324 000052AB E919010000          <1> 	jmp	dskrd_err
  2325                              <1> 	;
  2326                              <1> ;; return from preread
  2327                              <1> bread_2:
  2328                              <1> 	; 15/07/2022
  2329                              <1> 	;or	word [ebx], 4000h 
  2330                              <1> 	;	; bis $40000,(r5) 
  2331                              <1> 	;		; / set bit 14 of the 1st word of the I/O buffer
  2332                              <1> bread_3: ; 1:
  2333                              <1> 	; 15/07/2022
  2334                              <1> 	;test	word [ebx], 2400h
  2335                              <1> 	;	; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2336                              <1> 	;jz	short bread_4
  2337                              <1> 	;	; beq 1f / no
  2338                              <1> 	;	; cmp cdev,$1 / disk or drum?
  2339                              <1> 	;	; ble 2f / yes
  2340                              <1> 	;	; tstb uquant / is the time quantum = 0?
  2341                              <1> 	;	; bne 2f / no, 2f
  2342                              <1> 	;	; mov r5,-(sp) / yes, save r5 (buffer address)
  2343                              <1> 	;	; jsr r0,sleep; 31. 
  2344                              <1> 	;		; / put process to sleep in channel 31 (tape)
  2345                              <1> 	;	; mov (sp)+,r5 / restore r5
  2346                              <1> 	;	; br 1b / go back
  2347                              <1> ; 2: / drum or disk
  2348                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2349                              <1> 	;call	idle
  2350                              <1> 	;	; jsr r0,idle; s.wait+2 / wait
  2351                              <1> 	;jmp	short bread_3
  2352                              <1>        	;	; br 1b
  2353                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2354                              <1> 	;and	word [ebx], 0BFFFh ; 1011111111111111b
  2355                              <1> 	;	; bic $40000,(r5) / clear bit 14
  2356                              <1>        	;	; jsr r0,tstdeve / test device for error (tape)
  2357                              <1> 	; 15/07/2022
  2358 000052B0 83C308              <1> 	add	ebx, 8
  2359                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2360                              <1> 	; 09/06/2015
  2361 000052B3 66833D[51650000]00  <1> 	cmp	word [u.pcount], 0
  2362 000052BB 7705                <1> 	ja	short bread_5
  2363 000052BD E892F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2364                              <1> bread_5:
  2365                              <1> 	; EBX = system (I/O) buffer address
  2366 000052C2 E87C000000          <1> 	call	dioreg
  2367                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2368                              <1> 
  2369                              <1> 	; 19/07/2022
  2370                              <1> 	; EDI = user data offset (previous value of [u.pbase])
  2371                              <1> 	; ESI = pointer to file offset 
  2372                              <1> 	; EAX = system (I/O) buffer offset (>= EBX)
  2373                              <1> 	; ECX = byte count
  2374                              <1> 	; EBX = system buffer (data) address
  2375                              <1> 
  2376                              <1> 	; 19/07/2022
  2377 000052C7 010E                <1> 	add	[esi], ecx ; new file (disk) offset
  2378 000052C9 89C6                <1> 	mov	esi, eax
  2379                              <1> 
  2380                              <1> 	; esi = start address of the transfer (in the buffer)
  2381                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2382                              <1> 	; ecx = transfer count (in bytes)
  2383                              <1> 	;
  2384                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2385                              <1> ;   / of users data
  2386 000052CB F3A4                <1> 	rep	movsb
  2387                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2388                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2389                              <1>        		; bne 1b
  2390 000052CD 59                  <1> 	pop	ecx ; **
  2391 000052CE 833D[10650000]00    <1> 	cmp	dword [u.count], 0
  2392                              <1> 		; tst u.count / done
  2393 000052D5 77AC                <1> 	ja	short bread_0 ; 09/06/2015
  2394                              <1>        		; beq 1f / yes, return
  2395                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2396                              <1>        		; br bread / read some more
  2397                              <1> ; 1:
  2398 000052D7 58                  <1> 	pop	eax ; ****
  2399                              <1>        		; mov (sp)+,r0
  2400 000052D8 C3                  <1>         retn		; 09/06/2015
  2401                              <1> 	;jmp	ret_ 
  2402                              <1> 		;jmp ret  / jump to routine that called readi
  2403                              <1> 
  2404                              <1> 	; 08/02/2022
  2405                              <1> brw_oov_err:
  2406 000052D9 C705[41650000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2406 000052E1 0000                <1>
  2407 000052E3 E9E3DDFFFF          <1> 	jmp	error
  2408                              <1> 
  2409                              <1> 	; 08/02/2022
  2410                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2411                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2412                              <1> 	; 26/04/2013
  2413                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2414                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2415                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2416                              <1> 
  2417                              <1> 	; 08/02/2022
  2418                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2419                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2420                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2421                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2422                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2423                              <1> 
  2424                              <1> bwrite:
  2425                              <1> 	; 19/07/2022
  2426                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2427                              <1> 	; 15/07/2022
  2428                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2429                              <1> 	; 08/02/2022
  2430                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2431                              <1> 	; 14/07/2015
  2432                              <1> 	; 10/07/2015
  2433                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2434                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2435                              <1> 	;	
  2436                              <1> 	;; / write on block structured device
  2437                              <1> 	;
  2438                              <1> 	; INPUTS ->
  2439                              <1> 	;    [u.fofp] points to the block number
  2440                              <1> 	;    ECX = maximum block number allowed on device
  2441                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2442                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2443                              <1> 	;    [u.count]	number of bytes to user desires to write
  2444                              <1> 	; OUTPUTS ->
  2445                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2446                              <1> 	;
  2447                              <1> 	; ((Modified registers: EDX, ECX, EBX, ESI, EDI))
  2448                              <1> 	;
  2449                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2450                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2451                              <1> 	;	is increased by 1. For example: If user/program request 
  2452                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2453                              <1> 	;  	the next block number just as 512 byte writing is done.
  2454                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2455                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2456                              <1> 	;       enough to keep byte position/offset of the disk), this
  2457                              <1> 	;	defect will not be corrected, user/program must request
  2458                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2459                              <1> 	;       for achieving correct result. In future version(s), 
  2460                              <1> 	;	this defect will be corrected by using different 
  2461                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2462                              <1> 
  2463                              <1>        		; jsr r0,tstdeve / test the device for an error
  2464                              <1> 	;push	ecx ; **
  2465                              <1> 	; 26/04/2013
  2466                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2467 000052E8 2C03                <1> 	sub	al, 3
  2468                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2469 000052EA A2[54650000]        <1> 	mov	[u.brwdev], al
  2470                              <1> 	; 09/06/2015
  2471                              <1> 	;movzx	ebx, al
  2472                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2473                              <1> 	; 12/01/2022 (BugFix)
  2474 000052EF C0E002              <1> 	shl	al, 2 ; * 4
  2475 000052F2 8B88[525C0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2476                              <1> bwrite_0:
  2477 000052F8 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2478                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2479                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2480 000052F9 8B1D[FC640000]      <1> 	mov	ebx, [u.fofp]
  2481 000052FF 8B03                <1> 	mov	eax, [ebx]       
  2482 00005301 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2483                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2484 00005304 39C8                <1> 	cmp	eax, ecx
  2485                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2486                              <1>        	                     ; / block number allowed
  2487                              <1> 	;jnb	error	     ; 18/04/2013
  2488                              <1> 		; bhis error10 / yes, error
  2489                              <1>      	; 08/02/2022
  2490                              <1> 	;jb	short bwrite_1
  2491                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2492                              <1> 	;jmp	error
  2493 00005306 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2494                              <1> bwrite_1:
  2495                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2496                              <1> 		; inc *u.fofp / no, increment block number
  2497                              <1> 	; 09/06/2015 - 10/07/2015
  2498 00005308 66833D[51650000]00  <1> 	cmp	word [u.pcount], 0
  2499 00005310 7705                <1> 	ja	short bwrite_2
  2500 00005312 E839F8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2501                              <1> bwrite_2:
  2502 00005317 BF[54650000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2503 0000531C E8C9000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2504                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2505                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2506 00005321 E81D000000          <1>         call	dioreg
  2507                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2508                              <1> 
  2509                              <1> 	; 19/07/2022
  2510                              <1> 	; EDI = user data offset (previous value of [u.pbase])
  2511                              <1> 	; ESI = pointer to file offset 
  2512                              <1> 	; EAX = system (I/O) buffer offset (>= EBX)
  2513                              <1> 	; ECX = byte count
  2514                              <1> 	; EBX = system buffer (data) address
  2515                              <1> 
  2516                              <1> 	; 19/07/2022 - Erdogan Tan
  2517                              <1> 	; ((Against a possible disk write failure/error, 
  2518                              <1> 	;   file offset must not be updated/increased before 'dskwr'
  2519                              <1> 	;   but it was updated in 'dioreg'. I have modified 'dioreg'
  2520                              <1> 	;   and 'bwrite' procedures for that.))
  2521                              <1> 
  2522                              <1> 	; 19/07/2022
  2523 00005326 56                  <1> 	push	esi ; (!)  ; save file offset (pointer)
  2524 00005327 51                  <1> 	push	ecx ; (!!) ; save byte count
  2525                              <1> 	;mov	esi, eax
  2526                              <1> 	
  2527                              <1> 	; esi = destination address (in the buffer)
  2528                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2529                              <1> 	; ecx = transfer count (in bytes)
  2530                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2531                              <1> 	;xchg 	esi, edi ; 14/07/2015
  2532                              <1> 
  2533                              <1> 	; 19/07/2022
  2534 00005328 89FE                <1> 	mov	esi, edi
  2535 0000532A 89C7                <1> 	mov	edi, eax
  2536                              <1> 
  2537 0000532C F3A4                <1> 	rep	movsb
  2538                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2539                              <1>        		; dec r3 / area to the I/O buffer
  2540                              <1>        		; bne 1b
  2541                              <1> 
  2542 0000532E E8F0000000          <1> 	call	dskwr
  2543                              <1> 		; jsr r0,dskwr / write it out on the device
  2544                              <1> 
  2545                              <1> 	; 19/07/2022
  2546                              <1> 	; (there is not a disk write error, we can increase file offset)
  2547 00005333 58                  <1> 	pop	eax ; (!!) ; byte count
  2548 00005334 5F                  <1> 	pop	edi ; (!)  ; file offset (pointer)
  2549                              <1> 	;
  2550 00005335 0107                <1> 	add	[edi], eax ; new file offset (old offset + byte count)
  2551                              <1> 
  2552 00005337 59                  <1> 	pop	ecx ; **
  2553                              <1> 
  2554 00005338 833D[10650000]00    <1>         cmp     dword [u.count], 0
  2555                              <1> 		; tst u.count / done
  2556 0000533F 77B7                <1> 	ja	short bwrite_0 ; 09/06/2015
  2557                              <1> 		; beq 1f / yes, 1f
  2558                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2559                              <1>        		; br bwrite / go back and write next block
  2560                              <1> ; 1:
  2561 00005341 58                  <1> 	pop	eax ; ****
  2562                              <1>        		; mov (sp)+,r0
  2563 00005342 C3                  <1> 	retn		; 09/06/2015
  2564                              <1>         ;jmp	ret_ 
  2565                              <1> 		; jmp ret / return to routine that called writei
  2566                              <1> ;error10:
  2567                              <1> ;       jmp     error  ; / see 'error' routine
  2568                              <1> 
  2569                              <1> dioreg:
  2570                              <1> 	; 19/07/2022
  2571                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2572                              <1> 	; 04/02/2022
  2573                              <1> 	; 14/07/2015
  2574                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2575                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2576                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2577                              <1> 	;	
  2578                              <1> 	; bookkeeping on block transfers of data
  2579                              <1> 	;
  2580                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2581                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2582                              <1> 	; 10/07/2015
  2583                              <1> 	; * returns byte offset from beginning of current sector buffer
  2584                              <1> 	; (beginning of data) in ESI
  2585                              <1> 	
  2586                              <1> 	; 19/07/2022
  2587                              <1> 	; OUTPUTS:
  2588                              <1> 	;   EDI = user data offset (previous value of [u.pbase])
  2589                              <1> 	;   ESI = pointer to file offset 
  2590                              <1> 	;   EAX = system (I/O) buffer offset
  2591                              <1> 	;   ECX = byte count
  2592                              <1> 	;   EBX = system buffer (data) address	
  2593                              <1> 
  2594 00005343 8B0D[10650000]      <1> 	mov	ecx, [u.count]
  2595                              <1> 		; mov u.count,r3 / move char count to r3
  2596                              <1> 	; 04/02/2022
  2597 00005349 31D2                <1> 	xor	edx, edx
  2598 0000534B B602                <1> 	mov	dh, 2
  2599                              <1> 	; edx = 512
  2600 0000534D 39D1                <1> 	cmp	ecx, edx ; 512
  2601                              <1> 	;cmp 	ecx, 512
  2602                              <1> 		; cmp r3,$512. / more than 512. char?
  2603 0000534F 7602                <1> 	jna	short dioreg_0
  2604                              <1> 		; blos 1f / no, branch
  2605 00005351 89D1                <1> 	mov	ecx, edx ; 512
  2606                              <1> 	;mov	ecx, 512
  2607                              <1> 		; mov $512.,r3 / yes, just take 512.
  2608                              <1> dioreg_0:
  2609                              <1> 	; 09/06/2015
  2610 00005353 663B0D[51650000]    <1> 	cmp	cx, [u.pcount]
  2611 0000535A 7607                <1> 	jna	short dioreg_1
  2612 0000535C 668B0D[51650000]    <1> 	mov	cx, [u.pcount]
  2613                              <1> dioreg_1:
  2614                              <1> ; 1:
  2615 00005363 8B15[0C650000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2616                              <1> 	        ; mov u.base,r2 / put users base in r2
  2617 00005369 010D[14650000]      <1> 	add	[u.nread], ecx
  2618                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2619 0000536F 290D[10650000]      <1> 	sub	[u.count], ecx
  2620                              <1> 		; sub r3,u.count / update count
  2621 00005375 010D[0C650000]      <1> 	add	[u.base], ecx
  2622                              <1> 		; add r3,u.base / update base
  2623                              <1> 	; 10/07/2015
  2624                              <1> 	; Retro UNIX 386 v1 - modification !
  2625                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2626                              <1> 	; (It will point to next byte position instead of next block no.)
  2627 0000537B 8B35[FC640000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2628 00005381 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2629                              <1> 	; 19/07/2022
  2630                              <1> 	;add	[esi], ecx ; ecx is added to set the next byte position
  2631 00005383 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2632                              <1> 	;mov	esi, ebx   ; beginning of data in sector/block buffer
  2633                              <1> 	;add	esi, eax   ; esi contains start address of the transfer
  2634                              <1> 	; 19/07/2022
  2635 00005388 01D8                <1> 	add	eax, ebx   ; eax contains start address of the transfer	
  2636                              <1> 	; 09/06/2015 - 10/07/2015
  2637 0000538A 66290D[51650000]    <1> 	sub	[u.pcount], cx
  2638 00005391 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2639 00005397 8B3D[4D650000]      <1> 	mov	edi, [u.pbase]
  2640 0000539D 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2641 000053A3 01D7                <1> 	add	edi, edx
  2642 000053A5 893D[4D650000]      <1> 	mov	[u.pbase], edi
  2643 000053AB 010D[4D650000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2644 000053B1 C3                  <1> 	retn
  2645                              <1> 		; rts r0 / return
  2646                              <1> 
  2647                              <1> dskrd:
  2648                              <1> 	; 15/07/2022
  2649                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2650                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2651                              <1> 	; 18/08/2015
  2652                              <1> 	; 02/07/2015
  2653                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2654                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2655                              <1> 	;
  2656                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2657                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2658                              <1> 	; (number specified in r1) in the acquired buffer.)
  2659                              <1> 	; If the device is busy at the time dskrd is called,	
  2660                              <1> 	; dskrd calls idle.
  2661                              <1> 	; 
  2662                              <1> 	; INPUTS ->
  2663                              <1> 	;    r1 - block number
  2664                              <1> 	;    cdev - current device number 
  2665                              <1> 	; OUTPUTS ->
  2666                              <1> 	;    r5 - points to first data word in I/O buffer
  2667                              <1> 	;
  2668                              <1> 	; ((AX = R1)) input/output
  2669                              <1> 	; ((BX = R5)) output 
  2670                              <1> 	;
  2671                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI))  
  2672                              <1> 	;
  2673 000053B2 E8B5000000          <1> 	call 	bufaloc
  2674                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2675                              <1> 			       ; / get a free I/O buffer
  2676                              <1> 	;;jc	error ; 20/07/2013
  2677 000053B7 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2678                              <1>        		; br 1f / branch if block already in a I/O buffer
  2679                              <1> 
  2680                              <1> 	; 15/07/2022
  2681                              <1> 	; (buffer header byte 1, bit 2 is disk read bit/flag)
  2682                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2683 000053B9 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2684                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2685                              <1> 		               ; / I/O queue entry for buffer
  2686 000053BE E88E000000          <1> 	call	poke
  2687                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2688                              <1> 			    ; /	bit 10=1 says read
  2689                              <1> 	; 09/06/2015
  2690                              <1> 	;jnc	short dskrd_1
  2691                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2692                              <1> 	;jmp	error
  2693                              <1> 	; 08/02/2022
  2694 000053C3 7204                <1> 	jc	short dskrd_3
  2695                              <1> dskrd_1: ; 1:
  2696                              <1>        	; 15/07/2022
  2697                              <1> 	;
  2698                              <1> 	;	;clr *$ps
  2699                              <1>        	;test	word [ebx], 2400h
  2700                              <1> 	;	; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2701                              <1> 	;			; / jump to idle
  2702                              <1>        	;jz	short dskrd_2
  2703                              <1> 	;	; beq 1f
  2704                              <1>         ;;;mov   ecx, [s.wait_]
  2705                              <1>        	;call	idle
  2706                              <1> 	;	; jsr r0,idle; s.wait+2
  2707                              <1> 	;jmp 	short dskrd_1
  2708                              <1>        	;	; br 1b
  2709                              <1> dskrd_2: ; 1:
  2710 000053C5 83C308              <1>         add	ebx, 8
  2711                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2712                              <1> 			  ; / just read in
  2713 000053C8 C3                  <1>        	retn
  2714                              <1> 		; rts r0
  2715                              <1> dskrd_err: 
  2716                              <1> 	; 08/02/2022
  2717                              <1> 	; (jump from 'bread' error)	
  2718                              <1> dskrd_3:	
  2719                              <1> 	; 08/02/2022
  2720 000053C9 803D[54650000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2721 000053D0 7509                <1> 	jne	short dskrd_4 ; no
  2722                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2723 000053D2 C605[54650000]00    <1> 	mov	byte [u.brwdev], 0
  2724 000053D9 EB0A                <1> 	jmp	short dskrd_5
  2725                              <1> dskrd_4:
  2726 000053DB C705[41650000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2726 000053E3 0000                <1>
  2727                              <1> dskrd_5:
  2728 000053E5 E9E1DCFFFF          <1> 	jmp	error
  2729                              <1> 
  2730                              <1> bwslot:
  2731                              <1> 	; 15/07/2022
  2732                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2733                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2734                              <1> 	; 10/07/2015
  2735                              <1> 	;	If the block/sector is not placed in a buffer
  2736                              <1> 	;	before 'wslot', it must be read before
  2737                              <1> 	;	it is written! (Otherwise transfer counts less
  2738                              <1> 	;	than 512 bytes will be able to destroy existing 
  2739                              <1> 	;	data on disk.)
  2740                              <1> 	;
  2741                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2742                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2743                              <1> 	; Retro UNIX 8086 v1 modification !
  2744                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2745                              <1> 	; INPUT -> EDI - points to device id (in u.brwdev)	
  2746                              <1> 	;	-> EAX = block number
  2747                              <1> 	;
  2748 000053EA E88A000000          <1> 	call	bufaloc_0
  2749 000053EF 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2750                              <1> 	; 12/01/2022
  2751                              <1> 	; ebx = buffer header address
  2752                              <1> bwslot_0:
  2753                              <1> 	; 10/07/2015
  2754 000053F1 8B35[FC640000]      <1> 	mov	esi, [u.fofp]
  2755 000053F7 8B06                <1> 	mov	eax, [esi]
  2756 000053F9 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2757 000053FE 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2758                              <1> 		       ; recent disk data must be placed in the buffer
  2759 00005400 813D[10650000]0002- <1> 	cmp	dword [u.count], 512
  2759 00005408 0000                <1>
  2760 0000540A 730F                <1> 	jnb	short wslot_0	
  2761                              <1> bwslot_1:
  2762 0000540C E8A8FFFFFF          <1> 	call	dskrd_0
  2763                              <1> 	; 12/01/2022
  2764                              <1> 	; ebx = buffer data address = buffer header address + 8
  2765 00005411 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2766 00005414 EB05                <1> 	jmp 	short wslot_0
  2767                              <1> 
  2768                              <1> wslot:
  2769                              <1> 	; 15/07/2022
  2770                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2771                              <1> 	;
  2772                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2773                              <1> 	; 		(32 bit modifications)
  2774                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2775                              <1> 	;
  2776                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2777                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2778                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2779                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2780                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2781                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2782                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2783                              <1> 	;
  2784                              <1> 	; INPUTS ->
  2785                              <1>  	;    r1 - block number
  2786                              <1> 	;    cdev - current (block/disk) device number
  2787                              <1>  	;
  2788                              <1> 	; OUTPUTS ->
  2789                              <1> 	;    bufp - bits 9 and 15 are set, 
  2790                              <1> 	;           the remainder of the word left unchanged
  2791                              <1> 	;    r5 - points to first data word in I/O buffer
  2792                              <1> 	;
  2793                              <1> 	; ((AX = R1)) input/output
  2794                              <1> 	; ((BX = R5)) output 
  2795                              <1> 	;
  2796                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 
  2797                              <1> 
  2798 00005416 E851000000          <1> 	call	bufaloc
  2799                              <1> 	; 10/07/2015
  2800                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2801                              <1>         	; br 1f / word in buffer in r5
  2802                              <1> 	; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2803                              <1>         ; EAX = Block/Sector number (r1)
  2804                              <1> wslot_0: ;1:
  2805                              <1> 	; 14/07/2022
  2806                              <1> 	;
  2807                              <1>      	;test	word [ebx], 2400h
  2808                              <1> 	;	; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2809                              <1> 	;			; / of I/O queue entry
  2810                              <1> 	;jz	short wslot_1
  2811                              <1>         ;       ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2812                              <1> 	;	       ; / or not waiting to read)
  2813                              <1> 	;
  2814                              <1> 	;;mov	ecx, [s.wait_] ; 29/07/2013
  2815                              <1> 	;call	idle
  2816                              <1> 	;	; jsr r0,idle; / if buffer is reading or writing to read,
  2817                              <1>        	;                   ; / idle
  2818                              <1> 	;jmp	short wslot_0
  2819                              <1> 	;	; br 1b / till finished
  2820                              <1> wslot_1: ;1:
  2821                              <1> 	;or	word [ebx], 8200h
  2822                              <1>        	;	; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2823                              <1>         ;			; / (write, inhibit bits)
  2824                              <1> 	;	; clr *$ps / clear processor status
  2825                              <1> 
  2826                              <1> 	; 15/07/2022
  2827                              <1> 	; (set disk write bit/flag)
  2828                              <1> 	;or	word [ebx], 200h	
  2829 0000541B 43                  <1> 	inc	ebx
  2830 0000541C 800B02              <1> 	or	byte [ebx], 2
  2831 0000541F 83C307              <1> 	add	ebx, 7
  2832                              <1> 
  2833                              <1> 	;add	ebx, 8 ; 11/06/2015
  2834                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2835                              <1> 			  ; / for this block
  2836                              <1> dskwr_1:	; 08/02/2022
  2837 00005422 C3                  <1>        	retn
  2838                              <1> 		; rts r0
  2839                              <1> dskwr:
  2840                              <1> 	; 15/07/2022
  2841                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2842                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2843                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2844                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2845                              <1> 	;
  2846                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2847                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2848                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2849                              <1> 	; previously has supplied all the information required in the
  2850                              <1> 	; I/O queue entry.
  2851                              <1> 	;
  2852                              <1> 	; (Modified registers: ECX, EDX, EBX, ESI, EDI)
  2853                              <1> 	;
  2854                              <1> 	;
  2855 00005423 8B1D[A8640000]      <1> 	mov	ebx, [bufp]
  2856                              <1> 	; 15/07/2022
  2857                              <1> 	;and	word [ebx], 7FFFh ; 0111111111111111b
  2858                              <1> 	;	; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2859                              <1>                                   ; / bottom of queue
  2860                              <1> 	; 15/07/2022
  2861                              <1> 	; (set disk write bit)
  2862                              <1> 	; ('wslot' already sets disk write bit/flag)
  2863                              <1> 	;mov	word [ebx], 200h
  2864                              <1> 	
  2865 00005429 E823000000          <1> 	call	poke
  2866                              <1> 	; 09/06/2015
  2867 0000542E 73F2                <1> 	jnc	short dskwr_1
  2868                              <1> 	; 08/02/2022
  2869 00005430 803D[54650000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2870 00005437 7509                <1> 	jne	short dskwr_0 ; no
  2871                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2872 00005439 C605[54650000]00    <1> 	mov	byte [u.brwdev], 0
  2873 00005440 EB0A                <1> 	jmp	short dskwr_2
  2874                              <1> dskwr_0:
  2875 00005442 C705[41650000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2875 0000544A 0000                <1>
  2876                              <1> dskwr_2:
  2877 0000544C E97ADCFFFF          <1> 	jmp	error
  2878                              <1> ;dskwr_1:
  2879                              <1> ;	retn
  2880                              <1> 
  2881                              <1> ;ppoke:
  2882                              <1>        		; mov $340,*$ps
  2883                              <1>        		; jsr r0,poke
  2884                              <1>        		; clr *$ps
  2885                              <1> 		; rts r0
  2886                              <1> 
  2887                              <1> poke:
  2888                              <1> 	; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2889                              <1> 	; 14/07/2022
  2890                              <1> 	;	! Major Modification !
  2891                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2892                              <1> 	;
  2893                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2894                              <1> 	; 24/10/2015
  2895                              <1> 	; 20/08/2015
  2896                              <1> 	; 18/08/2015
  2897                              <1> 	; 02/07/2015
  2898                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2899                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2900                              <1> 	;
  2901                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2902                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2903                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2904                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2905                              <1> 	;
  2906                              <1> 	; Basic I/O functions for all block structured devices
  2907                              <1> 	;
  2908                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2909                              <1> 	;
  2910                              <1> 	; 20/07/2013 modifications
  2911                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2912                              <1> 	; INPUTS -> 
  2913                              <1> 	;        EBX = buffer header address
  2914                              <1> 	; OUTPUTS ->
  2915                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2916                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2917                              <1> 	;		(drive not ready or r/w error!)
  2918                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2919                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2920                              <1> 	;        (also it indicates invalid buffer data)
  2921                              <1> 	
  2922                              <1> 	; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2923                              <1> 	; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2924                              <1> 	; Buffer header:
  2925                              <1> 	;	byte 0 - device/disk (index) number
  2926                              <1> 	;	byte 1 - status
  2927                              <1> 	;	    before 'poke'	
  2928                              <1> 	;		bit 0 - valid bit 
  2929                              <1> 	;		   (0 for new buffer)
  2930                              <1> 	;		   (1 for existing buffer)	
  2931                              <1> 	;		bit 1 - write (modified) bit, disk write flag
  2932                              <1> 	;		bit 2 - read bit, disk read flag
  2933                              <1> 	;	    after 'poke'
  2934                              <1> 	;		if disk r/w is successed
  2935                              <1> 	;		   bit 0 = 1
  2936                              <1> 	;		   bit 1 = 0
  2937                              <1> 	;		   bit 2 = 0
  2938                              <1> 	;		if disk r/w is failed
  2939                              <1> 	;		   bit 0 = 0 (invalid buffer)
  2940                              <1> 	;		   bit 1 = 0 (write bit)
  2941                              <1> 	;		   bit 2 = 0 (read bit)	
  2942                              <1>  	;
  2943                              <1> 	;	byte 2 & byte 3 - not used
  2944                              <1> 	;	byte 4 to byte 7 - disk block/sector address
  2945                              <1> 	
  2946                              <1> 	; 04/02/2022
  2947 00005451 50                  <1> 	push	eax
  2948 00005452 E896000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2949 00005457 58                  <1> 	pop	eax
  2950 00005458 730D                <1> 	jnc	short seta ; 14/07/2022
  2951                              <1> 	
  2952                              <1> 	; 14/07/2022
  2953                              <1> 	; (invalidate buffer)
  2954                              <1> 	
  2955                              <1> 	; 02/07/2015 (32 bit modification)
  2956                              <1> 	; 20/07/2013
  2957 0000545A C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2958                              <1>        		; mov $-1,2(r1) / destroy associativity
  2959 00005461 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2960                              <1> 		; clrb 1(r1) / do not do I/O
  2961                              <1> 	;stc
  2962 00005466 C3                  <1> 	retn
  2963                              <1>         	; rts r0
  2964                              <1> seta: 
  2965 00005467 C6430101            <1> 	mov	byte [ebx+1], 1 ; clear write/read bits, set valid bit
  2966                              <1> 	;clc
  2967 0000546B C3                  <1> 	retn
  2968                              <1> 
  2969                              <1> %if 0
  2970                              <1> 
  2971                              <1> poke:
  2972                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2973                              <1> 	; 24/10/2015
  2974                              <1> 	; 20/08/2015
  2975                              <1> 	; 18/08/2015
  2976                              <1> 	; 02/07/2015
  2977                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2978                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2979                              <1> 	;
  2980                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2981                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2982                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2983                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2984                              <1> 	;
  2985                              <1> 	; Basic I/O functions for all block structured devices
  2986                              <1> 	;
  2987                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2988                              <1> 	;
  2989                              <1> 	; 20/07/2013 modifications
  2990                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2991                              <1> 	; INPUTS -> 
  2992                              <1> 	;        (EBX = buffer header address)
  2993                              <1> 	; OUTPUTS ->
  2994                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2995                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2996                              <1> 	;		(drive not ready or r/w error!)
  2997                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2998                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2999                              <1> 	;        (also it indicates invalid buffer data)
  3000                              <1> 	;
  3001                              <1> 	push	ebx
  3002                              <1>        		; mov r1,-(sp)
  3003                              <1>        		; mov r2,-(sp)
  3004                              <1>        		; mov r3,-(sp)
  3005                              <1> 	push 	eax ; Physical Block Number (r1) (mget)
  3006                              <1> 	;
  3007                              <1> 	; 09/06/2015
  3008                              <1> 	; (permit read/write after a disk  R/W error)
  3009                              <1> 	mov	cl, [ebx] ; device id (0 to 5)
  3010                              <1> 	mov	al, 1
  3011                              <1> 	shl	al, cl
  3012                              <1> 	test 	al, [active] ; busy ? (error)
  3013                              <1> 	jz	short poke_0
  3014                              <1> 	not	al
  3015                              <1> 	and	[active], al ; reset busy bit for this device only
  3016                              <1> poke_0:
  3017                              <1>         mov     esi, bufp + (4*(nbuf+2)) 
  3018                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  3019                              <1> 					 ; / I/O queue pointer
  3020                              <1> poke_1: ; 1:
  3021                              <1>         sub	esi, 4
  3022                              <1> 	mov	ebx, [esi]
  3023                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  3024                              <1> 	mov	ax, [ebx] ; 17/07/2013
  3025                              <1>        	test	ah, 06h
  3026                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  3027                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  3028                              <1> 			       ; / queue entry
  3029                              <1>         jz      short poke_5
  3030                              <1> 		; beq 2f / branch to 2f if both are clear
  3031                              <1> 	; 31/07/2013
  3032                              <1> 	;test	ah, 0B0h ; (*)
  3033                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  3034                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  3035                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  3036                              <1> 		; bne 2f / branch if any are set
  3037                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  3038                              <1>     		; movb (r1),r3 / get device id
  3039                              <1> 	movzx	ecx, al ; 18/08/2015
  3040                              <1> 	;mov	edi, ecx ; 26/04/2013
  3041                              <1> 	xor 	eax, eax ; 0
  3042                              <1> 	;cmp 	[edi+drv.error], al ; 0
  3043                              <1> 		; tstb deverr(r3) / test for errors on this device
  3044                              <1>        	;jna	short poke_2 
  3045                              <1> 		; beq 3f / branch if no errors
  3046                              <1> 	; 02/07/2015
  3047                              <1> 	;dec	eax
  3048                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  3049                              <1>        		; mov $-1,2(r1) / destroy associativity
  3050                              <1> 	;shr	eax, 24
  3051                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  3052                              <1> 		; clrb 1(r1) / do not do I/O
  3053                              <1> 	;jmp	short poke_5
  3054                              <1>         ;       ; br 2f
  3055                              <1>                 ; rts r0
  3056                              <1> poke_2: ; 3:
  3057                              <1> 	; 02/07/2015
  3058                              <1> 	inc	cl ; 0FFh -> 0
  3059                              <1> 	jz	short poke_5
  3060                              <1> 	inc	al ; mov ax, 1
  3061                              <1> 	dec	cl
  3062                              <1> 	jz	short poke_3
  3063                              <1> 	; 26/04/2013 Modification
  3064                              <1> 	;inc	al ; mov ax, 1
  3065                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  3066                              <1> 	;jz	short poke_3 ; cl = 0
  3067                              <1> 	shl	al, cl ; shl ax, cl
  3068                              <1> poke_3:
  3069                              <1> 	;test	[active], ax
  3070                              <1> 	test	[active], al
  3071                              <1> 		; bit $2,active / test disk busy bit
  3072                              <1> 	jnz     short poke_5
  3073                              <1> 		; bne 2f / branch if bit is set
  3074                              <1> 	;or	[active], ax
  3075                              <1> 	or	[active], al
  3076                              <1> 		; bis $2,active / set disk busy bit
  3077                              <1> 	;push	ax
  3078                              <1> 	; 24/12/2021
  3079                              <1> 	push	eax
  3080                              <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  3081                              <1> 	;mov    [edi+drv.error], ah
  3082                              <1> 	; 24/12/2021
  3083                              <1> 	pop	eax
  3084                              <1> 	;pop	ax
  3085                              <1> 	jnc	short poke_4 ; 20/07/2013
  3086                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  3087                              <1> 	;jna	short poke_4
  3088                              <1> 		; tstb deverr(r3) / test for errors on this device
  3089                              <1>        		; beq 3f / branch if no errors
  3090                              <1> 	; 02/07/2015 (32 bit modification)
  3091                              <1> 	; 20/07/2013
  3092                              <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  3093                              <1>        		; mov $-1,2(r1) / destroy associativity
  3094                              <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  3095                              <1> 		; clrb 1(r1) / do not do I/O
  3096                              <1> 	jmp     short poke_5
  3097                              <1> poke_4:	; 20/07/2013
  3098                              <1> 	; 17/07/2013
  3099                              <1> 	not 	al 
  3100                              <1> 	and	[active], al ; reset, not busy
  3101                              <1> 	; EBX = system I/O buffer header (queue entry) address
  3102                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  3103                              <1> 	mov	ax, [ebx]
  3104                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  3105                              <1>         and	ax, 600h
  3106                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  3107                              <1> 	and 	word [ebx], 0F9FFh
  3108                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  3109                              <1> 	shl	ah, 3
  3110                              <1>        		; rol r3
  3111                              <1>                 ; rol r3
  3112                              <1>                 ; rol r3	
  3113                              <1> 	or	[ebx], ax
  3114                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  3115                              <1> 			   ; bits 12 and 13
  3116                              <1> 	call	idle ; 18/01/2014
  3117                              <1> 	;; sti
  3118                              <1> 	;hlt 	; wait for a hardware interrupt
  3119                              <1> 	;; cli
  3120                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  3121                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  3122                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  3123                              <1> 	; method, this procedure will wait for a time according to
  3124                              <1> 	; multi tasking and time sharing concept.
  3125                              <1> 	;
  3126                              <1> 	; 24/10/2015
  3127                              <1> 	;not	ax 
  3128                              <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  3129                              <1> 	and	[ebx], ax ; clear bits 12 and 13
  3130                              <1> poke_5: ;2:
  3131                              <1>         cmp     esi, bufp
  3132                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  3133                              <1>                             ; / has been scanned
  3134                              <1> 	ja      short poke_1
  3135                              <1> 		; bhi 1b
  3136                              <1> 	; 24/03/2013
  3137                              <1>        		; mov (sp)+,r3
  3138                              <1>        		; mov (sp)+,r2
  3139                              <1>        		; mov (sp)+,r1
  3140                              <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  3141                              <1> 	pop 	ebx
  3142                              <1> 	; 02/07/2015 (32 bit modification)
  3143                              <1> 	; 20/07/2013
  3144                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  3145                              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  3146                              <1> 	;	
  3147                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  3148                              <1> 	; or written successfully; even if an error occurs while
  3149                              <1> 	; reading to or writing from other buffers. 20/07/2013
  3150                              <1> 	;
  3151                              <1> 	; 09/06/2015
  3152                              <1> 	cmc
  3153                              <1> 	retn
  3154                              <1>                 ; rts r0
  3155                              <1> 
  3156                              <1> %endif
  3157                              <1> 
  3158                              <1> bufaloc:
  3159                              <1> 	; 15/07/2022
  3160                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  3161                              <1> 	; 14/07/2022
  3162                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  3163                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3164                              <1> 	; 20/08/2015
  3165                              <1> 	; 19/08/2015
  3166                              <1> 	; 02/07/2015
  3167                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3168                              <1> 	;	     (32 bit modifications)	
  3169                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  3170                              <1> 	;
  3171                              <1> 	; bufaloc - Block device I/O buffer allocation
  3172                              <1> 	; 
  3173                              <1> 	; INPUTS ->
  3174                              <1> 	;    r1 - block number
  3175                              <1> 	;    cdev - current (block/disk) device number
  3176                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  3177                              <1> 	; OUTPUTS ->
  3178                              <1> 	;    r5 - pointer to buffer allocated
  3179                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  3180                              <1> 	;
  3181                              <1> 	; ((AX = R1)) input/output
  3182                              <1> 	; ((BX = R5)) output
  3183                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  3184                              <1> 	;    zf=1 -> block already in a I/O buffer
  3185                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  3186                              <1> 	;    ((DL = Device ID))
  3187                              <1> 	;    (((DH = 0 or 1)))
  3188                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  3189                              <1> 	;    ((CX and DH will not be used after return)))
  3190                              <1> 
  3191                              <1> 	; 14/07/2022
  3192                              <1> 	;	Modified registers: EBX, ECX, EDX, ESI, EDI
  3193                              <1> 
  3194                              <1> 	;;push 	esi ; ***
  3195                              <1> 		; mov r2,-(sp) / save r2 on stack
  3196                              <1>        		; mov $340,*$ps / set processor priority to 7
  3197                              <1> 	; 20/07/2013
  3198                              <1> 	; 26/04/2013
  3199                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  3200                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  3201                              <1> 	;add	edi, ebx
  3202                              <1> 	; 09/01/2022
  3203 0000546C 0FB63D[D3640000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  3204 00005473 81C7[D4640000]      <1> 	add	edi, rdev
  3205                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  3206                              <1> 			;; EDI points to device id.
  3207 00005479 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  3208                              <1> 	; 11/06/2015
  3209 0000547C 80BB[6E5C0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  3210 00005483 720F                <1> 	jb	short bufaloc_9
  3211 00005485 C705[41650000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3211 0000548D 0000                <1>
  3212 0000548F E937DCFFFF          <1> 	jmp	error
  3213                              <1> bufaloc_9:
  3214 00005494 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  3215                              <1> bufaloc_10: ; 02/07/2015
  3216                              <1> 	; 14/07/2022
  3217                              <1> 	;xor 	ebp, ebp ; 0
  3218                              <1> 	;push	ebp ; 0
  3219                              <1>         ;mov	ebp, esp	
  3220 00005496 31FF                <1> 	xor	edi, edi ; 0	
  3221 00005498 57                  <1> 	push	edi
  3222                              <1> bufaloc_1: ;1:
  3223                              <1> 		; clr -(sp) / vacant buffer
  3224 00005499 BE[A8640000]        <1>         mov 	esi, bufp
  3225                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3226                              <1> 			     ; / entrys in buffer area
  3227                              <1> bufaloc_2: ;2:
  3228 0000549E 8B1E                <1> 	mov	ebx, [esi]
  3229                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3230                              <1> 			    ; queue entry into r5
  3231                              <1> 	; 14/07/2022
  3232 000054A0 8B0B                <1> 	mov	ecx, [ebx]	
  3233                              <1> 	;test	word [ebx], 0F600h
  3234                              <1> 	; 15/07/2022
  3235 000054A2 F6C501              <1> 	test	ch, 1 ; valid buffer (content) ?
  3236                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3237 000054A5 7505                <1>         jnz	short bufaloc_3 ; yes
  3238                              <1> 		; bne 3f / branch when 
  3239                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3240                              <1>                        ; / (i.e., buffer busy)
  3241                              <1> 	;mov    [ebp], esi ; pointer to I/0 queue entry
  3242                              <1> 	; 14/07/2022
  3243                              <1> 	; save free buffer pointer 
  3244 000054A7 893424              <1> 	mov	[esp], esi
  3245                              <1>                 ; mov r2,(sp) ;/ save pointer to last non-busy buffer
  3246                              <1> 			; / found points to word 2 of I/O queue entry)
  3247                              <1> 	; continue to see if requested sector/block buffer
  3248                              <1> 	;	already is one of existing (valid) buffers
  3249                              <1> 	;jmp	short bufaloc_4
  3250 000054AA EB0E                <1> 	jmp	short bufaloc_11 ; 14/07/2022
  3251                              <1> bufaloc_3: ;3:
  3252                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3253                              <1> 	;
  3254 000054AC 38D1                <1> 	cmp	cl, dl ; 14/07/2022
  3255                              <1> 	;cmp	[ebx], dl	
  3256                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3257                              <1> 			       ; / as current device
  3258 000054AE 7508                <1> 	jne	short bufaloc_4
  3259                              <1>        		; bne 3f
  3260 000054B0 394304              <1> 	cmp	[ebx+4], eax
  3261                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3262                              <1> 			     ; / same as current block number
  3263 000054B3 7503                <1>        	jne	short bufaloc_4
  3264                              <1> 		; bne 3f
  3265                              <1> 	;add	esp, 4
  3266 000054B5 59                  <1> 	pop	ecx
  3267                              <1>        		; tst (sp)+ / bump stack pointer
  3268 000054B6 EB1D                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3269                              <1> 				; jump to bufaloc_6 in original Unix v1
  3270                              <1>        		; br 1f / use this buffer
  3271                              <1> bufaloc_4: ;3:
  3272                              <1> 	; 14/07/2022
  3273                              <1> 	; save last valid buffer 
  3274                              <1> 	; (will be used if there is not a free buffer)
  3275 000054B8 89F7                <1> 	mov	edi, esi	
  3276                              <1> bufaloc_11:
  3277 000054BA 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3278                              <1> 	;
  3279 000054BD 81FE[C8640000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3280                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3281 000054C3 72D9                <1> 	jb	short bufaloc_2
  3282                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3283                              <1>                        ; / buffers not checked)
  3284 000054C5 5E                  <1>         pop	esi
  3285                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3286                              <1> 			     ; / to last free block
  3287 000054C6 09F6                <1>        	or	esi, esi 
  3288 000054C8 7502                <1> 	jnz	short bufaloc_5
  3289                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3290                              <1> 	        ; / if a free buffer is found branch to 2f
  3291                              <1> 
  3292                              <1> 	; 14/07/2022        
  3293                              <1> 	; if there is not a free buffer
  3294                              <1> 	; we can use last valid buffer (the oldest buffer)
  3295                              <1> 	; ((ptr to new buffer is located at head of buff ptr chain))
  3296 000054CA 89FE                <1> 	mov	esi, edi
  3297                              <1> 
  3298                              <1> 	;;mov  ecx, [s.wait_]
  3299                              <1> 	;call	idle
  3300                              <1> 	;	; jsr r0,idle; s.wait+2 / idle if no free buffers
  3301                              <1> 	;jmp 	short bufaloc_10 ; 02/07/2015
  3302                              <1>        	;	; br 1b
  3303                              <1> bufaloc_5: ;2:
  3304                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3305                              <1> 	; 14/07/2022
  3306                              <1> 	;inc	dh ; Retro UNIX 8086 v1 modification
  3307                              <1> bufaloc_6: ;1:
  3308 000054CC 8B1E                <1>         mov    	ebx, [esi] 
  3309                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3310                              <1> 			     ; / entry in r5
  3311                              <1> 	;; 26/04/2013
  3312                              <1>         ;;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3313                              <1> 	;mov 	[ebx], dl
  3314                              <1> 		; movb cdev,(r5) / put current device number 
  3315                              <1> 				 ; / in I/O queue entry
  3316                              <1> 	; 14/07/2022
  3317                              <1> 	; invalidate buffer before r/w (new) disk sector/block
  3318                              <1> 	;mov	[ebx+1], dh ; 0
  3319                              <1> 	; 14/07/2022
  3320 000054CE 8913                <1> 	mov	[ebx], edx  ; dh = 0
  3321                              <1> 	
  3322 000054D0 894304              <1> 	mov 	[ebx+4], eax
  3323                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3324                              <1> 			     ; / of I/O queue entry
  3325                              <1> 	; 14/07/2022
  3326 000054D3 FEC6                <1> 	inc	dh ; dh = 1
  3327                              <1> bufaloc_7: ;1:
  3328 000054D5 81FE[A8640000]      <1>         cmp	esi, bufp
  3329                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3330                              <1> 			     ; / and put latest assigned
  3331 000054DB 760B                <1> 	jna	short bufaloc_8	
  3332                              <1>        		; blos 1f / buffer on the top 
  3333                              <1> 			; / (this makes if the lowest priority)
  3334                              <1> 	; 14/07/2022
  3335 000054DD 89F7                <1> 	mov	edi, esi
  3336 000054DF 83EE04              <1> 	sub	esi, 4
  3337 000054E2 8B0E                <1> 	mov	ecx, [esi]
  3338 000054E4 890F                <1> 	mov	[edi], ecx ; 14/07/2022
  3339                              <1> 	;mov	[esi+4], ecx
  3340                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3341 000054E6 EBED                <1> 	jmp 	short bufaloc_7        
  3342                              <1> 		; br 1b
  3343                              <1> bufaloc_8: ;1:
  3344 000054E8 891E                <1>         mov	[esi], ebx
  3345                              <1> 		; mov r5,(r2)
  3346                              <1> 	;;pop	esi ; ***
  3347                              <1>        		; mov (sp)+,r2 / restore r2
  3348 000054EA 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3349                              <1> 		; Retro UNIX 8086 v1 modification
  3350                              <1> 		; zf=1 --> block already is in an I/O buffer
  3351                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3352 000054EC C3                  <1> 	retn
  3353                              <1> 		; rts r0
  3354                              <1> 
  3355                              <1> diskio:
  3356                              <1> 	; 12/07/2022
  3357                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3358                              <1> 	;	((simplified and shortened 'diskio.s' code))
  3359                              <1> 	; 12/02/2022
  3360                              <1> 	; 10/02/2022
  3361                              <1> 	; 08/02/2022
  3362                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3363                              <1> 	; 10/07/2015
  3364                              <1> 	; 02/07/2015
  3365                              <1> 	; 16/06/2015
  3366                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3367                              <1> 	;	     (80386 protected mode modifications)	
  3368                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3369                              <1> 	;
  3370                              <1> 	; Retro UNIX 8086 v1 feature only !
  3371                              <1> 	;
  3372                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3373                              <1> 	; 04/07/2009 - 20/07/2011
  3374                              <1> 	;
  3375                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3376                              <1> 	;
  3377                              <1>         ; INPUTS ->
  3378                              <1> 	; 	   EBX = System I/O Buffer header address
  3379                              <1> 	;
  3380                              <1>         ; OUTPUTS -> cf=0 --> done 
  3381                              <1> 	; 	     cf=1 --> error code in AH
  3382                              <1> 	;	     ; 08/02/2022
  3383                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3384                              <1> 	;		error code in [u.error]
  3385                              <1> 	;		
  3386                              <1> 	; (Modified registers: EAX, ECX, EDX)
  3387                              <1> 	
  3388                              <1> ;rw_disk_sector:
  3389                              <1> 	; 12/07/2022
  3390                              <1> 	; 08/07/2022
  3391                              <1> 	; 12/02/2022
  3392                              <1> 	; 10/02/2022
  3393                              <1> 	; 08/02/2022
  3394                              <1> 	; 10/07/2015
  3395                              <1> 	; 02/07/2015
  3396                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3397                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3398                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3399                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3400                              <1> 	;
  3401                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3402                              <1> 	;mov	dh, 2
  3403                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3404 000054ED B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3405 000054EF 668B03              <1> 	mov	ax, [ebx] 
  3406                              <1> 	;
  3407 000054F2 56                  <1> 	push	esi ; ****
  3408 000054F3 53                  <1> 	push	ebx ; ***
  3409                              <1> 	;
  3410 000054F4 0FB6C8              <1> 	movzx	ecx, al
  3411 000054F7 89CE                <1> 	mov	esi, ecx
  3412                              <1> 	;
  3413 000054F9 38F1                <1> 	cmp	cl, dh ; 2
  3414 000054FB 7202                <1> 	jb	short rwdsk0
  3415 000054FD 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3416                              <1> rwdsk0:
  3417                              <1> 	; 12/07/2022
  3418                              <1> 	;mov	[drv], al
  3419 000054FF 81C6[6E5C0000]      <1> 	add	esi, drv.status
  3420                              <1> 	; 11/06/2015
  3421 00005505 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3422 00005508 7204                <1> 	jb      short rwdsk1
  3423                              <1> 	; 'drive not ready' error
  3424                              <1> 	; 10/02/2022
  3425                              <1> 	; 08/02/2022
  3426                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3427                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3428                              <1> 	;;jmp	error
  3429                              <1> 	;stc	; cf = 1
  3430                              <1> 	;retn
  3431                              <1> 	; 10/02/2022
  3432 0000550A B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3433 0000550C EB1F                <1> 	jmp	short rwdsk_err1
  3434                              <1> rwdsk1:
  3435                              <1> 	;test	ah, 2
  3436                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3437                              <1> 	;		 ; write bit
  3438                              <1> 	;jz	short rwdsk2
  3439                              <1> 	
  3440                              <1> 	;;test	ah, 4
  3441                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3442                              <1> 	;;		 ; read bit
  3443                              <1> 	;;jz	short diskio_ret
  3444                              <1> 
  3445                              <1> 	;inc	dh ; 03h = write
  3446                              <1> 
  3447                              <1> 	; 08/07/2022
  3448 0000550E 84F4                <1> 	test	ah, dh ; test ah, 2
  3449 00005510 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3450 00005512 FECE                <1> 	dec	dh
  3451                              <1> 		; dh = 01h = read
  3452                              <1> rwdsk2:
  3453 00005514 88C2                <1> 	mov	dl, al
  3454 00005516 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3455 00005519 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3456 0000551B C0E102              <1> 	shl	cl, 2
  3457 0000551E 81C1[525C0000]      <1> 	add	ecx, drv.size ; disk size
  3458 00005524 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3459 00005526 7214                <1> 	jb      short rwdsk3
  3460                              <1>  	; 'out of volume' error
  3461                              <1> 	; 10/02/2022
  3462                              <1> 	; 08/02/2022
  3463                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3464                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3465                              <1> 	;;jmp	error
  3466                              <1> 	;stc	; cf = 1
  3467                              <1> 	;retn
  3468                              <1> 	; 10/02/2022
  3469 00005528 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3470                              <1> rwdsk_err1:
  3471 0000552D C605[54650000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3472 00005534 890D[41650000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3473 0000553A EB27                <1> 	jmp	short rwdsk_err2
  3474                              <1> rwdsk3:
  3475                              <1> 	; 11/06/2015
  3476 0000553C 83C304              <1> 	add	ebx, 4 ; buffer address
  3477 0000553F C605[72650000]04    <1> 	mov	byte [retry_count], 4
  3478                              <1> 	; 12/07/2022
  3479                              <1> 	;test	byte [esi], 1 ; LBA ready ?
  3480                              <1>         ;jz	short rwdsk_chs
  3481                              <1> rwdsk_lba:
  3482                              <1> 	; LBA read/write (with private LBA function) 
  3483                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3484 00005546 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3485 00005549 89C1                <1> 	mov	ecx, eax ; sector number
  3486                              <1> 	; ebx = buffer (data) address
  3487                              <1> 	; dl = physical drive number (0, 1, 80h, 81h, 82h, 83h)
  3488                              <1> rwdsk_lba_retry:
  3489                              <1> 	;mov	dl, [drv]
  3490                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3491                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3492                              <1> 	;;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3493                              <1> 	;mov	ah, 2 ; LBA write function number - 2
  3494                              <1> 	;add	ah, dh		
  3495                              <1> 	;mov	al, 1
  3496                              <1> 	;int	13h
  3497                              <1> 	;call	int13h
  3498                              <1> 	; 12/07/2022
  3499 0000554B 88F0                <1> 	mov	al, dh	; function (1 or 2)
  3500                              <1> 			; (1 = read, 2 = write )
  3501                              <1> 	; ecx = disk sector address (LBA)
  3502                              <1> 	; ebx = buffer address
  3503                              <1> 	;  dl = (physical) disk number
  3504                              <1> 	;  al = function (r/w)
  3505 0000554D E8FCC9FFFF          <1> 	call	DISK_IO
  3506                              <1> 
  3507 00005552 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3508 00005554 730E                <1> 	jnc	short rwdsk_lba_ok
  3509 00005556 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3510 00005559 7408                <1>         je      short rwdsk_lba_fails
  3511 0000555B FE0D[72650000]      <1> 	dec	byte [retry_count]
  3512 00005561 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3513                              <1> rwdsk_err2:	; 10/02/2022
  3514                              <1> rwdsk_lba_fails:
  3515 00005563 F9                  <1> 	stc
  3516                              <1> rwdsk_lba_ok:
  3517 00005564 5B                  <1> 	pop	ebx ; ***
  3518 00005565 5E                  <1> 	pop	esi ; ****
  3519 00005566 C3                  <1> 	retn
  3520                              <1> rwdsk_lba_reset:
  3521                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3522                              <1> 	;int	13h
  3523                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3524                              <1> 	;mov	ah, 5 ; Alternate reset	 
  3525                              <1> 	;call	int13h
  3526                              <1> 	;jnc	short rwdsk_lba_retry
  3527                              <1> 	; 12/07/2022
  3528 00005567 30C0                <1> 	xor	al, al ; 0 ; reset
  3529 00005569 E8E0C9FFFF          <1> 	call	DISK_IO
  3530 0000556E 73DB                <1> 	jnc	short rwdsk_lba_retry
  3531                              <1> 
  3532 00005570 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3533 00005572 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3534                              <1> 
  3535                              <1> 	; 12/07/2022 
  3536                              <1> 	;	(CHS Read/Write setup is not needed here.)
  3537                              <1> 	; 	(LBA address will be converted to CHS parameters 
  3538                              <1> 	;	in 'DISK_IO' procedure when/if it is required.)
  3539                              <1>  
  3540                              <1> ;	; CHS read (convert LBA address to CHS values)	
  3541                              <1> ;rwdsk_chs:
  3542                              <1> ;	; 10/07/2015
  3543                              <1> ;	sub	esi, drv.status
  3544                              <1> ;	mov	ecx, esi
  3545                              <1> ;	add 	esi, drv.error
  3546                              <1> ;	; 02/07/2015
  3547                              <1> ;	; 16/06/2015
  3548                              <1> ;	; 11/06/2015 
  3549                              <1> ;	push	ebx ; ** ; buffer
  3550                              <1> ;	shl	ecx, 1
  3551                              <1> ;	push	ecx ; * 
  3552                              <1> ;	;
  3553                              <1> ;	mov	ebx, ecx
  3554                              <1> ;	mov	[rwdsk], dh ; 02/07/2015
  3555                              <1> ;	xor	edx, edx ; 0
  3556                              <1> ;	; 09/01/2022
  3557                              <1> ;	;sub	ecx, ecx 
  3558                              <1> ;       add     ebx, drv.spt
  3559                              <1> ;	mov	cx, [ebx] ; sector per track
  3560                              <1> ;		; EDX:EAX = LBA
  3561                              <1> ;	div	ecx
  3562                              <1> ;	mov	cl, dl	; sector number - 1
  3563                              <1> ;	inc	cl	; sector number (1 based)
  3564                              <1> ;	pop	ebx ; * ; 11/06/2015
  3565                              <1> ;	;push	cx
  3566                              <1> ;	; 09/01/2022
  3567                              <1> ;	push	ecx
  3568                              <1> ;	add     ebx, drv.heads
  3569                              <1> ;	mov	cx, [ebx] ; heads
  3570                              <1> ;	xor	edx, edx
  3571                              <1> ;		; EAX = cylinders * heads + head
  3572                              <1> ;	div	ecx
  3573                              <1> ;	;pop	cx     ; sector number
  3574                              <1> ;	; 09/01/2022
  3575                              <1> ;	pop	ecx
  3576                              <1> ;	mov	dh, dl ; head number
  3577                              <1> ;	mov	dl, [drv]
  3578                              <1> ;	mov	ch, al ; cylinder (bits 0-7)
  3579                              <1> ;	shl	ah, 6
  3580                              <1> ;	or	cl, ah ; cylinder (bits 8-9)
  3581                              <1> ;		       ; sector (bits 0-7)
  3582                              <1> ;	pop	ebx ; ** ; buffer ; 11/06/2015
  3583                              <1> ;		; CL = sector (bits 0-5)
  3584                              <1> ;		;      cylinder (bits 8-9 -> bits 6-7)
  3585                              <1> ;		; CH = cylinder (bits 0-7)
  3586                              <1> ;		; DH = head
  3587                              <1> ;		; DL = drive
  3588                              <1> ;	;
  3589                              <1> ;	mov	byte [retry_count], 4
  3590                              <1> ;rwdsk_retry:	
  3591                              <1> ;	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3592                              <1> ;	; 08/07/2022
  3593                              <1> ;	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3594                              <1> ;	mov	al, 1 ; sector count	
  3595                              <1> ;	;int	13h
  3596                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3597                              <1> ;	call	int13h
  3598                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3599                              <1> ;	jnc	short rwdsk_ok ; ah = 0
  3600                              <1> ;	cmp	ah, 80h ; time out ?
  3601                              <1> ;	je	short rwdsk_fails
  3602                              <1> ;	dec	byte [retry_count]
  3603                              <1> ;	jnz	short rwdsk_reset
  3604                              <1> ;rwdsk_fails:
  3605                              <1> ;	stc
  3606                              <1> ;rwdsk_ok:
  3607                              <1> ;	pop	ebx ; ***
  3608                              <1> ;	pop	esi ; ****
  3609                              <1> ;	retn
  3610                              <1> ;rwdsk_reset:
  3611                              <1> ;	; 02/02/2015
  3612                              <1> ;	sub	ah, ah
  3613                              <1> ;	cmp	dl, 80h
  3614                              <1> ;	jb	short rwdsk_fd_reset
  3615                              <1> ;	;mov	ah, 0Dh ; Alternate reset
  3616                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3617                              <1> ;	mov	ah, 5  ; Alternate reset
  3618                              <1> ;rwdsk_fd_reset:
  3619                              <1> ;	;int	13h
  3620                              <1> ;	call	int13h
  3621                              <1> ;	jnc	short rwdsk_retry
  3622                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3623                              <1> ;	jmp 	short rwdsk_ok
  3624                              <1> 
  3625                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3626                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3627                              <1> ;
  3628                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3629                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3630                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3631                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3632                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3633                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3634                              <1> ; as in original unix v1.
  3635                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3636                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3637                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3638                              <1> ;
  3639                              <1> ; Erdogan tan (10/07/2015) 
  3640                              <1> 
  3641                              <1> ;drum: / interrupt handler
  3642                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3643                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3644                              <1> ;                                      / error
  3645                              <1> ;               br 3f / no, error
  3646                              <1> ;       br      2f / error
  3647                              <1> ;
  3648                              <1> ;disk:
  3649                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3650                              <1> ;       jmp     *$0f
  3651                              <1> ;0:
  3652                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3653                              <1> ;      	        br 3f / no, errors
  3654                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3655                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3656                              <1> ;                        / to 1f
  3657                              <1> ;       br      4f
  3658                              <1> ;1:
  3659                              <1> ;       bit     $20000,rkcs
  3660                              <1> ;       beq     4f / wait for seek complete
  3661                              <1> ;       mov     $0b,0b-2
  3662                              <1> ;       mov     rkap,r1
  3663                              <1> ;2:
  3664                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3665                              <1> ;                          / the disk buffer
  3666                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3667                              <1> ;       inc     r1
  3668                              <1> ;       asr     (r1)
  3669                              <1> ;       asr     (r1)
  3670                              <1> ;       asr     (r1) / reissue request
  3671                              <1> ;       dec     r1
  3672                              <1> ;3:
  3673                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3674                              <1> ;       mov     ac,-(sp)
  3675                              <1> ;       mov     mq,-(sp) / put these on the stack
  3676                              <1> ;       mov     sc,-(sp)
  3677                              <1> ;       jsr     r0,poke
  3678                              <1> ;       mov     (sp)+,sc
  3679                              <1> ;       mov     (sp)+,mq / pop them off stack
  3680                              <1> ;       mov     (sp)+,ac
  3681                              <1> ;4:
  3682                              <1> ;       jmp     retisp / u4-3
  3683                              <1> ;
  3684                              <1> ;trapt:                  / r2 points to the
  3685                              <1> ;       mov     (r0)+,r2 / device control register
  3686                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3687                              <1> ;       tst     (sp)+
  3688                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3689                              <1> ;       bge     4b / device still active so branch
  3690                              <1> ;       bit     (r0),active / was device busy?
  3691                              <1> ;       beq     4b / no, stray interrupt
  3692                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3693                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3694                              <1> ;       bge     2f / if no error jump to 2f
  3695                              <1> ;       tst     (r0)+ / skip on error
  3696                              <1> ; 2:
  3697                              <1> ;       jmp     (r0)
  2122                                  %include 'u9.s'        ; 29/06/2015
  2123                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS9.INC
  2124                              <1> ; Last Modification: 13/06/2022
  2125                              <1> ; ----------------------------------------------------------------------------
  2126                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2127                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2128                              <1> ;
  2129                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2130                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2131                              <1> ; <Bell Laboratories (17/3/1972)>
  2132                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2133                              <1> ;
  2134                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2135                              <1> ;
  2136                              <1> ; ****************************************************************************
  2137                              <1> 
  2138                              <1> getch:
  2139                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2140                              <1> 	; 30/06/2015
  2141                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2142 00005574 28C0                <1> 	sub	al, al ; 0
  2143                              <1> getch_q: ; 06/08/2015
  2144 00005576 8A25[56610000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2145 0000557C EB06                <1>         jmp     short getc_n
  2146                              <1> 
  2147                              <1> getc: 
  2148                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2149                              <1> 	; 12/11/2015
  2150                              <1> 	; 15/09/2015
  2151                              <1> 	; 01/07/2015
  2152                              <1> 	; 30/06/2015
  2153                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2154                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2155                              <1> 	;
  2156                              <1> 	; Retro UNIX 8086 v1 modification !
  2157                              <1> 	; 
  2158                              <1> 	; 'getc' gets (next) character 
  2159                              <1> 	;	 from requested TTY (keyboard) buffer 
  2160                              <1> 	; INPUTS ->
  2161                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2162                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2163                              <1> 	;	(Keyboard buffer will point to 
  2164                              <1> 	;			next character at next call)
  2165                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2166                              <1> 	;	(Keyboard buffer will point to 
  2167                              <1> 	;			current character at next call)
  2168                              <1> 	; OUTPUTS ->
  2169                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2170                              <1> 	;     			 ZF=0 -> AX has (current) character
  2171                              <1> 	;      AL = ascii code
  2172                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2173                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2174                              <1> 	; Original UNIX V1 'getc': 
  2175                              <1> 	;		get a character off character list
  2176                              <1> 	;
  2177                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2178                              <1> 	;
  2179                              <1> 	; 30/06/2015 (32 bit modifications)
  2180                              <1> 	; 16/07/2013
  2181                              <1> 	; mov 	[getctty], ah
  2182                              <1> 	;
  2183                              <1> 
  2184 0000557E 8A25[40650000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2185                              <1> getc_n:
  2186                              <1> 	; 30/06/2015
  2187 00005584 08E4                <1> 	or	ah, ah
  2188 00005586 740D                <1> 	jz	short getc0 
  2189 00005588 D0E4                <1> 	shl	ah, 1
  2190 0000558A 0FB6DC              <1> 	movzx	ebx, ah
  2191 0000558D 81C3[58610000]      <1> 	add	ebx, ttychr
  2192 00005593 EB05                <1> 	jmp	short getc1
  2193                              <1> getc0:
  2194 00005595 BB[58610000]        <1> 	mov	ebx, ttychr
  2195                              <1> getc1:
  2196 0000559A 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2197                              <1> 				; (by kb_int)	
  2198 0000559D 6609C9              <1> 	or	cx, cx
  2199 000055A0 7507                <1> 	jnz	short getc2
  2200 000055A2 20C0                <1> 	and 	al, al
  2201 000055A4 7415                <1> 	jz	short getc_s
  2202                              <1> 	;xor	ax, ax
  2203                              <1> 	; 24/12/2021
  2204 000055A6 31C0                <1> 	xor	eax, eax
  2205 000055A8 C3                  <1> 	retn
  2206                              <1> getc2:	
  2207 000055A9 20C0                <1> 	and	al, al
  2208 000055AB 6689C8              <1> 	mov	ax, cx
  2209 000055AE 66B90000            <1> 	mov	cx, 0
  2210 000055B2 7506                <1> 	jnz	short getc3
  2211                              <1> getc_sn:
  2212 000055B4 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2213 000055B7 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2214                              <1> getc3:
  2215 000055BA C3                  <1> 	retn
  2216                              <1> getc_s:
  2217                              <1> 	; 12/11/2015
  2218                              <1> 	; 15/09/2015
  2219                              <1> 	; 01/07/2015
  2220                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2221                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2222                              <1> 	;
  2223                              <1> 	; tty  of the current process is not 
  2224                              <1> 	; current tty (ptty); so, current process only 
  2225                              <1> 	; can use keyboard input when its tty becomes 
  2226                              <1> 	; current tty (ptty).
  2227                              <1> 	; 'sleep' is for preventing an endless lock
  2228                              <1> 	; during this tty input request.
  2229                              <1> 	; (Because, the user is not looking at the video page
  2230                              <1> 	; of the process to undersand there is a keyboard
  2231                              <1> 	; input request.)
  2232                              <1> 	;
  2233                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2234                              <1> 	;
  2235                              <1> 	; 05/10/2013
  2236                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2237                              <1> 	;
  2238                              <1> 	; 10/10/2013
  2239                              <1> gcw0:
  2240 000055BB B10A                <1> 	mov	cl, 10 ; ch = 0
  2241                              <1> gcw1:	
  2242                              <1> 	; 12/11/2015
  2243 000055BD E816DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2244                              <1> 	; 10/10/2013
  2245 000055C2 E8B2EFFFFF          <1> 	call	idle
  2246 000055C7 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2247                              <1> 				; (by kb_int)
  2248 000055CA 6609C0              <1> 	or	ax, ax
  2249                              <1> ;	jnz	short gcw3
  2250 000055CD 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2251                              <1> 	; 30/06/2015
  2252 000055CF FEC9                <1> 	dec	cl
  2253 000055D1 75EA                <1> 	jnz	short gcw1
  2254                              <1> 	;
  2255 000055D3 8A25[40650000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2256                              <1> ;	; 10/12/2013
  2257                              <1> ;	cmp 	ah, [ptty]
  2258                              <1> ;	jne	short gcw2
  2259                              <1> ;	; 14/02/2014
  2260                              <1> ;	cmp	byte [u.uno], 1
  2261                              <1> ;	jna	short gcw0		
  2262                              <1> ;gcw2:
  2263 000055D9 E828F0FFFF          <1> 	call	sleep
  2264                              <1> 	;
  2265                              <1> 	; 20/09/2013
  2266 000055DE 8A25[40650000]      <1> 	mov	ah, [u.ttyn]
  2267 000055E4 30C0                <1> 	xor 	al, al
  2268 000055E6 EB9C                <1> 	jmp	short getc_n
  2269                              <1> ;gcw3:
  2270                              <1> gcw2: 	; 15/09/2015
  2271                              <1> 	; 10/10/2013
  2272 000055E8 30C9                <1> 	xor	cl, cl
  2273 000055EA EBC8                <1> 	jmp	short getc_sn
  2274                              <1> 
  2275                              <1> putc:	
  2276                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2277                              <1> 	; 13/08/2015
  2278                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2279                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2280                              <1> 	;
  2281                              <1> 	; Retro UNIX 8086 v1 modification !
  2282                              <1> 	; 
  2283                              <1> 	; 'putc' puts a character 
  2284                              <1> 	;	 onto requested (tty) video page or
  2285                              <1> 	;	 serial port
  2286                              <1> 	; INPUTS ->
  2287                              <1> 	;     AL = ascii code of the character
  2288                              <1> 	;     AH = video page (tty) number (0 to 7)
  2289                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2290                              <1> 	; OUTPUTS ->
  2291                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2292                              <1> 	;      			ZF=0 -> AX has (current) character
  2293                              <1> 	;     cf=0 and AH = 0 -> no error
  2294                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2295                              <1> 	; 
  2296                              <1> 	; Original UNIX V1 'putc': 
  2297                              <1> 	;     put a character at the end of character list
  2298                              <1> 	;
  2299                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2300                              <1> 	;
  2301 000055EC 80FC07              <1> 	cmp	ah, 7
  2302                              <1>         ;ja	sndc
  2303 000055EF 770A                <1>         ja      short sndc ; 24/12/2024
  2304                              <1> 	; 30/06/2015
  2305 000055F1 0FB6DC              <1> 	movzx	ebx, ah
  2306                              <1> 	; 13/08/2015
  2307 000055F4 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2308 000055F6 E9A1BCFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2309                              <1> 
  2310                              <1> sndc:   ; <Send character>
  2311                              <1> 	;
  2312                              <1> 	; 12/01/2022
  2313                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2314                              <1> 	; 17/11/2015
  2315                              <1> 	; 16/11/2015
  2316                              <1> 	; 11/11/2015
  2317                              <1> 	; 10/11/2015
  2318                              <1> 	; 09/11/2015
  2319                              <1> 	; 08/11/2015
  2320                              <1> 	; 07/11/2015
  2321                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2322                              <1> 	; 29/10/2015
  2323                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2324                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2325                              <1> 	;
  2326                              <1> 	; Retro UNIX 8086 v1 feature only !
  2327                              <1> 	;
  2328                              <1> 	; ah = [u.ttyn]
  2329                              <1> 	;
  2330                              <1> 	; 30/06/2015
  2331 000055FB 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2332                              <1> 	; 07/11/2015
  2333 000055FE 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2334                              <1> sndc0:
  2335                              <1> 	; 07/11/2015
  2336 00005601 E84EF0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2337 00005606 7405                <1> 	jz	short sndc1
  2338 00005608 E8CBDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2339                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2340                              <1> sndc1:
  2341                              <1> 	; 16/11/2015
  2342                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2343                              <1> 	; 24/12/2021
  2344 0000560D 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2345                              <1> sndcx:
  2346 0000560F 8A83[9A610000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2347 00005615 8AA3[98610000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2348                              <1> 	;
  2349                              <1> 	; 17/11/2015
  2350                              <1> 	; check 'request for response' status
  2351 0000561B 80BB[94610000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2352 00005622 740A                <1> 	jz	short query
  2353                              <1> response:
  2354 00005624 FE05[97610000]      <1> 	inc 	byte [comqr] ; query or response status
  2355 0000562A B0FF                <1> 	mov	al, 0FFh	 
  2356 0000562C EB14                <1> 	jmp	short sndc3
  2357                              <1> query:
  2358 0000562E 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2359 00005630 750E                <1> 	jnz 	short sndc2 ; normal character
  2360                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2361                              <1> 	;je	short sndc2  ; yes, already responded
  2362                              <1> 	; 16/11/2015
  2363                              <1> 	; query: request for response (again)
  2364 00005632 8883[98610000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2365 00005638 FE05[97610000]      <1> 	inc 	byte [comqr] ; query or response status
  2366 0000563E EB02                <1> 	jmp	short sndc3
  2367                              <1> sndc2:
  2368 00005640 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2369                              <1> sndc3:
  2370 00005642 8883[9A610000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2371 00005648 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2372                              <1> 	; 30/06/2015
  2373 0000564A E832D5FFFF          <1> 	call	sp_status ; get serial port status
  2374                              <1> 	; AL = Line status, AH = Modem status
  2375                              <1> 	; 07/11/2015
  2376 0000564F A880                <1> 	test	al, 80h
  2377 00005651 7504                <1> 	jnz	short sndc4
  2378 00005653 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2379 00005655 751A                <1> 	jnz	short sndc5
  2380                              <1> sndc4: 	; Check line status again
  2381                              <1> 	; 16/11/2015
  2382                              <1> 	;push	cx
  2383                              <1> 	; 24/12/2021
  2384 00005657 51                  <1> 	push	ecx
  2385                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2386                              <1> 	; 12/01/2022
  2387 00005658 31C9                <1> 	xor	ecx, ecx
  2388 0000565A B106                <1> 	mov	cl, 6
  2389 0000565C E832BDFFFF          <1> 	call	WAITF
  2390                              <1> 	;pop	cx
  2391                              <1> 	; 24/12/1021
  2392 00005661 59                  <1> 	pop	ecx
  2393                              <1> 	;
  2394 00005662 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2395 00005664 E818D5FFFF          <1> 	call	sp_status ; get serial port status
  2396                              <1> 	; 16/11/2015
  2397                              <1> 	; 09/11/2015
  2398                              <1> 	; 08/11/2015
  2399 00005669 A880                <1> 	test	al, 80h	; time out error
  2400 0000566B 7565                <1>         jnz     short sndc7
  2401 0000566D A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2402 0000566F 7461                <1>         jz	short sndc7
  2403                              <1> sndc5:  
  2404 00005671 8A83[9A610000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2405 00005677 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2406 0000567B 28DE                <1> 	sub	dh, bl
  2407 0000567D EE                  <1> 	out	dx, al	   ; send on serial port
  2408                              <1> 	; 10/11/2015
  2409                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2410                              <1> 	; (to improve text flow to the terminal)
  2411                              <1> 	; ('diskette.inc': 'WAITF')
  2412                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2413                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2414                              <1> 	;push	cx
  2415                              <1> 	; 24/12/2021
  2416 0000567E 51                  <1> 	push	ecx
  2417                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2418                              <1> 	; 12/01/2022
  2419 0000567F 29C9                <1> 	sub	ecx, ecx
  2420 00005681 B106                <1> 	mov	cl, 6
  2421 00005683 E80BBDFFFF          <1> 	call	WAITF
  2422                              <1> 	;pop	cx
  2423                              <1> 	; 24/12/1021
  2424 00005688 59                  <1> 	pop	ecx
  2425                              <1>     	;
  2426                              <1> 	; 07/11/2015
  2427 00005689 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2428                              <1> 	;
  2429 0000568B E8F1D4FFFF          <1> 	call	sp_status ; get serial port status
  2430                              <1> 	; AL = Line status, AH = Modem status
  2431                              <1> 	;
  2432 00005690 E8BFEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2433 00005695 7405                <1> 	jz	short sndc6
  2434 00005697 E83CDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2435                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2436                              <1> sndc6:
  2437 0000569C 3C80                <1> 	cmp	al, 80h
  2438 0000569E 7332                <1> 	jnb	short sndc7		
  2439                              <1> 	;
  2440 000056A0 803D[97610000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2441 000056A7 7244                <1> 	jb	short sndc8 	; no, normal character
  2442 000056A9 883D[97610000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2443                              <1> 	; 17/11/2015
  2444 000056AF E8C5EEFFFF          <1> 	call	idle
  2445                              <1> 	;
  2446 000056B4 38BB[9A610000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2447                              <1>         ;ja	sndc2       ; response (will be followed by
  2448                              <1> 			    ; a normal character)
  2449                              <1> 	; 24/12/2021
  2450 000056BA 7602                <1> 	jna	short sndc_10
  2451 000056BC EB82                <1> 	jmp	sndc2
  2452                              <1> sndc_10:
  2453                              <1> 	; Query request must be responded by the terminal
  2454                              <1> 	; before sending a normal character !
  2455 000056BE 53                  <1> 	push	ebx
  2456                              <1> 	;push	cx ; *** cl = character (to be sent)
  2457                              <1> 	; 24/12/2021
  2458 000056BF 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2459 000056C0 8A25[40650000]      <1> 	mov	ah, [u.ttyn]
  2460 000056C6 E83BEFFFFF          <1> 	call	sleep ; this process will be awakened by
  2461                              <1> 		      ; received data available interrupt
  2462                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2463                              <1> 	; 24/12/2021
  2464 000056CB 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2465 000056CC 5B                  <1> 	pop	ebx
  2466 000056CD E93DFFFFFF          <1>         jmp	sndcx
  2467                              <1> sndc7:
  2468                              <1> 	 ; 16/11/2015
  2469 000056D2 803D[97610000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2470 000056D9 7213                <1> 	jb	short sndc9 	; no
  2471                              <1> 	;
  2472 000056DB 88BB[98610000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2473 000056E1 88BB[9A610000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2474                              <1> 	;
  2475 000056E7 883D[97610000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2476                              <1> sndc8:
  2477 000056ED F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2478                              <1> sndc9:
  2479                              <1> 	; AL = Line status, AH = Modem status
  2480 000056EE C3                  <1> 	retn
  2481                              <1> 
  2482                              <1> get_cpos:
  2483                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2484                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2485                              <1> 	;
  2486                              <1> 	; INPUT -> bl = video page number
  2487                              <1> 	; RETURN -> dx = cursor position
  2488                              <1> 
  2489 000056EF 53                  <1> 	push	ebx
  2490 000056F0 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2491 000056F3 D0E3                <1> 	shl	bl, 1
  2492 000056F5 81C3[46610000]      <1> 	add	ebx, cursor_posn
  2493 000056FB 668B13              <1> 	mov	dx, [ebx]
  2494 000056FE 5B                  <1> 	pop	ebx
  2495 000056FF C3                  <1> 	retn
  2496                              <1> 
  2497                              <1> read_ac_current:
  2498                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2499                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2500                              <1> 	;
  2501                              <1> 	; INPUT -> bl = video page number
  2502                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2503                              <1> 
  2504 00005700 E8FDBCFFFF          <1> 	call 	find_position ; 'video.inc'
  2505                              <1> 	; dx = status port
  2506                              <1> 	; esi = cursor location/address
  2507 00005705 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2508 0000570B 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2509 0000570E C3                  <1> 	retn
  2510                              <1> 
  2511                              <1> syssleep:
  2512                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2513                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2514                              <1> 	;
  2515                              <1> 	; Retro UNIX 8086 v1 feature only
  2516                              <1> 	; (INPUT -> none)
  2517                              <1> 	;
  2518 0000570F 0FB61D[3B650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2519 00005716 8AA3[43620000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2520 0000571C E8E5EEFFFF          <1> 	call	sleep
  2521 00005721 E9C5D9FFFF          <1> 	jmp	sysret
  2522                              <1> 
  2523                              <1> 	; 27/02/2022
  2524                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2525                              <1> %if 0
  2526                              <1> 
  2527                              <1> vp_clr:
  2528                              <1> 	; Reset/Clear Video Page
  2529                              <1> 	;
  2530                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2531                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2532                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2533                              <1> 	;
  2534                              <1> 	; Retro UNIX 8086 v1 feature only !
  2535                              <1> 	;
  2536                              <1> 	; INPUTS -> 
  2537                              <1> 	;   BL = video page number	 
  2538                              <1> 	;
  2539                              <1> 	; OUTPUT ->
  2540                              <1> 	;   none
  2541                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2542                              <1> 	;
  2543                              <1> 	; 04/12/2013
  2544                              <1> 	sub	al, al
  2545                              <1> 	; al = 0 (clear video page)
  2546                              <1> 	; bl = video page
  2547                              <1> 	mov	ah, 07h
  2548                              <1> 	; ah = 7 (attribute/color)
  2549                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2550                              <1> 	; 24/12/2021
  2551                              <1> 	xor	ecx, ecx
  2552                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2553                              <1> 	call	scroll_up
  2554                              <1> 	; bl = video page
  2555                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2556                              <1> 	; 24/12/2021
  2557                              <1> 	xor	edx, edx 
  2558                              <1> 	jmp 	set_cpos
  2559                              <1> 
  2560                              <1> %endif
  2561                              <1> 
  2562                              <1> sysmsg:
  2563                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2564                              <1> 	; 11/11/2015
  2565                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2566                              <1> 	; Print user-application message on user's console tty
  2567                              <1> 	;
  2568                              <1> 	; Input -> EBX = Message address
  2569                              <1> 	;	   ECX = Message length (max. 255)
  2570                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2571                              <1> 	;
  2572 00005726 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2573                              <1> 	;ja	sysret ; nothing to do with big message size
  2574 0000572C 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2575 0000572E 08C9                <1> 	or	cl, cl
  2576                              <1> 	;jz	sysret
  2577 00005730 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2578 00005732 20D2                <1> 	and	dl, dl
  2579 00005734 7502                <1> 	jnz	short sysmsg0
  2580 00005736 B207                <1> 	mov	dl, 07h ; default color
  2581                              <1> 		; (black background, light gray character)
  2582                              <1> sysmsg0:
  2583 00005738 891D[0C650000]      <1> 	mov	[u.base], ebx
  2584 0000573E 8815[57610000]      <1> 	mov	[ccolor], dl ; color attributes
  2585 00005744 89E5                <1> 	mov	ebp, esp
  2586 00005746 31DB                <1> 	xor	ebx, ebx ; 0
  2587 00005748 891D[14650000]      <1> 	mov	[u.nread], ebx ; 0
  2588                              <1> 	;
  2589 0000574E 381D[53650000]      <1> 	cmp	[u.kcall], bl ; 0
  2590 00005754 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2591                              <1> 	;
  2592 00005756 890D[10650000]      <1> 	mov	[u.count], ecx
  2593 0000575C 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2594                              <1> 	; 24/12/2021
  2595                              <1> 	; (dword alignment for esp)
  2596 0000575D F6C103              <1> 	test	cl, 3
  2597 00005760 7404                <1> 	jz	short sysmsg_7
  2598 00005762 80C903              <1> 	or	cl, 3
  2599 00005765 41                  <1> 	inc	ecx
  2600                              <1> sysmsg_7:
  2601 00005766 29CC                <1> 	sub	esp, ecx
  2602 00005768 89E7                <1> 	mov	edi, esp
  2603 0000576A 89E6                <1> 	mov	esi, esp
  2604 0000576C 66891D[51650000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2605                              <1> 	; 11/11/2015
  2606 00005773 8A25[1C650000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2607                              <1> 	; 0 = none
  2608 00005779 FECC                <1> 	dec	ah
  2609 0000577B 790C                <1> 	jns	short sysmsg1 
  2610 0000577D 8A1D[3B650000]      <1> 	mov	bl, [u.uno] ; process number	
  2611 00005783 8AA3[43620000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2612                              <1> sysmsg1:
  2613 00005789 8825[40650000]      <1> 	mov	[u.ttyn], ah
  2614                              <1> sysmsg2:
  2615 0000578F E84BF6FFFF          <1> 	call	cpass
  2616 00005794 7416                <1> 	jz	short sysmsg5
  2617 00005796 AA                  <1> 	stosb
  2618 00005797 20C0                <1> 	and	al, al
  2619 00005799 75F4                <1> 	jnz	short sysmsg2
  2620                              <1> sysmsg3:
  2621 0000579B 80FC07              <1> 	cmp	ah, 7 ; tty number
  2622 0000579E 7711                <1> 	ja	short sysmsg6 ; serial port
  2623 000057A0 E83E000000          <1> 	call	print_cmsg
  2624                              <1> sysmsg4:
  2625 000057A5 89EC                <1> 	mov	esp, ebp	
  2626                              <1> sysmsg8: ; 24/12/2021	
  2627 000057A7 E93FD9FFFF          <1> 	jmp	sysret
  2628                              <1> sysmsg5:
  2629 000057AC C60700              <1> 	mov	byte [edi], 0
  2630 000057AF EBEA                <1> 	jmp	short sysmsg3
  2631                              <1> sysmsg6:
  2632 000057B1 8A06                <1> 	mov	al, [esi]
  2633 000057B3 E843FEFFFF          <1> 	call	sndc
  2634 000057B8 72EB                <1> 	jc	short sysmsg4
  2635 000057BA 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2636 000057BD 76E6                <1> 	jna	short sysmsg4
  2637 000057BF 46                  <1> 	inc 	esi
  2638 000057C0 8A25[40650000]      <1> 	mov	ah, [u.ttyn]
  2639 000057C6 EBE9                <1> 	jmp	short sysmsg6
  2640                              <1> 
  2641                              <1> sysmsgk: ; Temporary (01/07/2015)
  2642                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2643                              <1> 	; (ECX -character count- will not be considered)
  2644 000057C8 8B35[0C650000]      <1> 	mov	esi, [u.base]
  2645 000057CE 8A25[56610000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2646 000057D4 8825[40650000]      <1> 	mov	[u.ttyn], ah
  2647 000057DA C605[53650000]00    <1> 	mov	byte [u.kcall], 0
  2648 000057E1 EBB8                <1> 	jmp	short sysmsg3
  2649                              <1> 	
  2650                              <1> print_cmsg: 
  2651                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2652                              <1> 	;
  2653                              <1> 	; print message (on user's console tty) 
  2654                              <1> 	;	with requested color
  2655                              <1> 	;
  2656                              <1> 	; INPUTS:
  2657                              <1> 	;	esi = message address
  2658                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2659                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2660                              <1> 	;
  2661 000057E3 AC                  <1> 	lodsb
  2662                              <1> pcmsg1:
  2663 000057E4 56                  <1> 	push 	esi
  2664 000057E5 0FB61D[40650000]    <1>         movzx   ebx, byte [u.ttyn]
  2665 000057EC 8A25[57610000]      <1> 	mov	ah, [ccolor]
  2666 000057F2 E8A5BAFFFF          <1> 	call 	write_tty
  2667 000057F7 5E                  <1> 	pop	esi
  2668 000057F8 AC                  <1> 	lodsb
  2669 000057F9 20C0                <1> 	and 	al, al  ; 0
  2670 000057FB 75E7                <1> 	jnz 	short pcmsg1
  2671 000057FD C3                  <1> 	retn
  2672                              <1> 
  2673                              <1> sysgeterr:
  2674                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2675                              <1> 	; 09/12/2015
  2676                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2677                              <1> 	; Get last error number or page fault count
  2678                              <1> 	; (for debugging)
  2679                              <1> 	;
  2680                              <1> 	; Input -> EBX = return type
  2681                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2682                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2683                              <1> 	;	   FFFFFFFEh = total page fault count
  2684                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2685                              <1> 	;
  2686                              <1> 	; Output -> EAX = last error number or page fault count
  2687                              <1> 	;	   (depending on EBX input)
  2688                              <1> 	; 	
  2689 000057FE 21DB                <1> 	and 	ebx, ebx
  2690 00005800 750F                <1> 	jnz	short glerr_2
  2691                              <1> glerr_0:
  2692 00005802 A1[41650000]        <1> 	mov	eax, [u.error]
  2693                              <1> glerr_1:
  2694 00005807 A3[EC640000]        <1> 	mov	[u.r0], eax
  2695                              <1>  	;retn
  2696                              <1> 	; 16/02/2022 (BugFix)
  2697 0000580C E9DAD8FFFF          <1> 	jmp	sysret
  2698                              <1> glerr_2:
  2699 00005811 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2700 00005812 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2701 00005814 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2702 00005815 75EB                <1> 	jnz	short glerr_0
  2703 00005817 A1[DC610000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2704 0000581C EBE9                <1>         jmp     short glerr_1
  2705                              <1> glerr_3:
  2706 0000581E A1[55650000]        <1> 	mov 	eax, [u.pfcount]
  2707 00005823 EBE2                <1> 	jmp	short glerr_1
  2708                              <1> 
  2709                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2710                              <1> ;	     - PRINTER BIOS (Functions)		
  2711                              <1> 
  2712                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2713                              <1> ;
  2714                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2715                              <1> ; PRINTER_IO								       :
  2716                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2717                              <1> ; INPUT 								       :
  2718                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2719                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2720                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2721                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2722                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2723                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2724                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2725                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2726                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2727                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2728                              <1> ;		   |	   |	   |	   |	   |			       :
  2729                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2730                              <1> ;		   |	   |	   |	   |				       :
  2731                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2732                              <1> ;		   |	   |	   |					       :
  2733                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2734                              <1> ;		   |	   |						       :
  2735                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2736                              <1> ;		   |							       :
  2737                              <1> ;		   |_ 1 = NOT BUSY					       :
  2738                              <1> ;									       :
  2739                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2740                              <1> ;		IN @PRINTER_BASE AREA					       :
  2741                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2742                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2743                              <1> ;									       :
  2744                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2745                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2746                              <1> ;									       :
  2747                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2748                              <1> ;		ALL OTHERS UNCHANGED					       :
  2749                              <1> ;-------------------------------------------------------------------------------
  2750                              <1> 
  2751                              <1> int17h:
  2752                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2753                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2754                              <1> 	;
  2755                              <1> 	; (Default printer port: 378h) ; LPT1
  2756                              <1> 	; (Number of printers = 1)
  2757                              <1> 	
  2758                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2759                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2760                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2761                              <1> 
  2762                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2763                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2764                              <1> 
  2765                              <1> 	; INPUT:
  2766                              <1> 	;	ah = 0 -> print the character in AL 
  2767                              <1> 	;		 (sys write with write count >0)
  2768                              <1> 	;	ah = 1 -> initialize printer port
  2769                              <1> 	;		 (sys open)	
  2770                              <1> 	;	ah = 2 -> read the printer status 
  2771                              <1> 	;		 (sys write with write count = 0)
  2772                              <1> 	; OUTPUT:
  2773                              <1> 	;	ah = printer status
  2774                              <1> 
  2775                              <1> 	; Modified registers: eax, ecx, edx
  2776                              <1> 
  2777                              <1> PRINTER_IO_1:
  2778 00005825 08E4                <1> 	or	ah, ah
  2779 00005827 7417                <1> 	jz	short _b20
  2780 00005829 FECC                <1> 	dec	ah
  2781 0000582B 7444                <1> 	jz	short _b80
  2782                              <1> 	;dec 	ah
  2783                              <1> 	;jz	short _b50
  2784                              <1> _b50:
  2785                              <1> 	;-----	PRINTER STATUS
  2786                              <1> B50:
  2787 0000582D 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2788                              <1> B60:
  2789 0000582E 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2790                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2791                              <1> 				; POINT TO CONTROL PORT
  2792 00005832 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2793 00005833 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2794 00005834 88C4                <1> 	mov	ah, al		; SAVE
  2795 00005836 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2796                              <1> B70:
  2797 00005839 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2798 0000583A 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2799 0000583C 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2800                              <1> B10:
  2801 0000583F C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2802                              <1> _b20:
  2803                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2804 00005840 B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2805                              <1> B20:
  2806 00005845 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2807 00005846 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2808 0000584A EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2809 0000584B FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2810                              <1> 
  2811                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2812                              <1> B25:
  2813                              <1> 	;-----	WAIT BUSY
  2814                              <1> B35:
  2815 0000584D EC                  <1> 	in	al, dx		; GET STATUS
  2816 0000584E 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2817 00005850 A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2818 00005852 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2819 00005854 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2820 00005859 E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2821                              <1> 
  2822 0000585B 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2823 0000585E 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2824 00005861 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2825                              <1> 
  2826                              <1> B40:				; SEND STROBE PULSE
  2827 00005863 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2828 00005865 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2829 00005867 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2830 00005868 EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2831                              <1> 	; IODELAY
  2832                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2833                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2834                              <1> 	; NEWIODELAY
  2835 00005869 E6EB                <1> 	out	0EBh, al
  2836                              <1> 
  2837 0000586B B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2838 0000586D EE                  <1> 	out	dx, al
  2839 0000586E FB                  <1> 	sti			; INTERRUPTS BACK ON
  2840                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2841                              <1> 	;jmp	short B50
  2842 0000586F EBBD                <1> 	jmp	short B60
  2843                              <1> 
  2844                              <1> _b80:
  2845                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2846                              <1> B80:
  2847 00005871 50                  <1> 	push	eax		; SAVE (AL)
  2848 00005872 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2849 00005876 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2850 00005878 EE                  <1> 	out	dx, al
  2851                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2852 00005879 B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2853                              <1> B90:				; INIT_LOOP
  2854                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2855                              <1> 	;jnz	short B90	; INIT_LOOP
  2856 0000587E E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2857 00005883 E2F9                <1> 	loop	B90	
  2858 00005885 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2859 00005887 EE                  <1> 	out	dx, al
  2860 00005888 EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2861                              <1> 
  2862                              <1> 
  2863                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2864                              <1> ; -------------------------------------------------------------------
  2865                              <1> ;
  2866                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2867                              <1> ;;65536/30 = 2185
  2868                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2869                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2870                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2871                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2872                              <1> ;
  2873                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2874                              <1> ;
  2875                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2876                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2877                              <1> ;;1,080,000 / 30 = 36,000
  2878                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2879                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2880                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2881                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2882                              <1> ;
  2883                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2884                              <1> 
  2885                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2886                              <1> ; ------------------------------------------
  2887                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2888                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2889                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2890                              <1> ;	OUTPUT: BX:CX destroyed.
  2891                              <1> ;
  2892                              <1> ;	SAVES:	AX (except when NO STACK)
  2893                              <1> ;
  2894                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2895                              <1> ;		used this way, AX is assumed to be destroyed.
  2896                              <1> 
  2897                              <1> WAIT_REFRESH:
  2898                              <1> 	; 13/06/2022
  2899                              <1> 	; Modified for Retro UNIX 386 v1.1
  2900                              <1> 	
  2901                              <1> 	; (wait for 30 micro seconds)
  2902                              <1> 
  2903                              <1> 	SYS1	equ 61h ; PORT_B
  2904                              <1> 
  2905                              <1> WR_SHORT:
  2906 0000588A 50                  <1> 	push	eax
  2907                              <1> WR_STAT_0:
  2908 0000588B E461                <1> 	in	al, SYS1	; wait for high to low
  2909 0000588D A810                <1> 	test	al, 10h		; transition on memory
  2910 0000588F 75FA                <1> 	jnz	short WR_STAT_0 
  2911                              <1> WR_STAT_1:
  2912 00005891 E461                <1> 	in	al, SYS1
  2913 00005893 A810                <1> 	test	al, 10h
  2914 00005895 74FA                <1> 	jz	short WR_STAT_1
  2915 00005897 58                  <1> 	pop	eax
  2916 00005898 C3                  <1> 	retn
  2123                                  
  2124                                  ; 07/03/2015
  2125                                  ; Temporary Code
  2126                                  display_disks:
  2127 00005899 803D[4C5C0000]00        	cmp 	byte [fd0_type], 0
  2128 000058A0 7605                    	jna 	short ddsks1
  2129 000058A2 E87D000000              	call	pdskm
  2130                                  ddsks1:
  2131 000058A7 803D[4D5C0000]00        	cmp	byte [fd1_type], 0
  2132 000058AE 760C                    	jna	short ddsks2
  2133 000058B0 C605[135E0000]31        	mov	byte [dskx], '1'
  2134 000058B7 E868000000              	call	pdskm
  2135                                  ddsks2:
  2136 000058BC 803D[4E5C0000]00        	cmp	byte [hd0_type], 0
  2137 000058C3 7654                    	jna	short ddsk6
  2138 000058C5 66C705[115E0000]68-     	mov	word [dsktype], 'hd'
  2138 000058CD 64                 
  2139 000058CE C605[135E0000]30        	mov	byte [dskx], '0'
  2140 000058D5 E84A000000              	call	pdskm
  2141                                  ddsks3:
  2142 000058DA 803D[4F5C0000]00        	cmp	byte [hd1_type], 0
  2143 000058E1 7636                    	jna	short ddsk6
  2144 000058E3 C605[135E0000]31        	mov	byte [dskx], '1'
  2145 000058EA E835000000              	call	pdskm
  2146                                  ddsks4:
  2147 000058EF 803D[505C0000]00        	cmp	byte [hd2_type], 0
  2148 000058F6 7621                    	jna	short ddsk6
  2149 000058F8 C605[135E0000]32        	mov	byte [dskx], '2'
  2150 000058FF E820000000              	call	pdskm
  2151                                  ddsks5:
  2152 00005904 803D[515C0000]00        	cmp	byte [hd3_type], 0
  2153 0000590B 760C                    	jna	short ddsk6
  2154 0000590D C605[135E0000]33        	mov	byte [dskx], '3'
  2155 00005914 E80B000000              	call	pdskm
  2156                                  ddsk6:
  2157 00005919 BE[225E0000]            	mov	esi, nextline
  2158 0000591E E806000000              	call	pdskml
  2159                                  pdskm_ok:
  2160 00005923 C3                      	retn
  2161                                  pdskm:
  2162 00005924 BE[0F5E0000]            	mov	esi, dsk_ready_msg
  2163                                  pdskml:	
  2164 00005929 AC                      	lodsb
  2165 0000592A 08C0                    	or	al, al
  2166 0000592C 74F5                    	jz	short pdskm_ok
  2167 0000592E 56                      	push	esi
  2168 0000592F 31DB                    	xor	ebx, ebx ; 0
  2169                                  			; Video page 0 (bl=0)
  2170 00005931 B407                    	mov	ah, 07h ; Black background, 
  2171                                  			; light gray forecolor
  2172 00005933 E864B9FFFF              	call	write_tty
  2173 00005938 5E                      	pop	esi
  2174 00005939 EBEE                    	jmp	short pdskml
  2175                                  
  2176 0000593B 90<rep 5h>              align 16
  2177                                  
  2178                                  gdt:	; Global Descriptor Table
  2179                                  	; (30/07/2015, conforming cs)
  2180                                  	; (26/03/2015)
  2181                                  	; (24/03/2015, tss)
  2182                                  	; (19/03/2015)
  2183                                  	; (29/12/2013)
  2184                                  	;
  2185 00005940 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2186                                  	; 18/08/2014
  2187                                  			; 8h kernel code segment, base = 00000000h		
  2188 00005948 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2189                                  			; 10h kernel data segment, base = 00000000h	
  2190 00005950 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2191                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2192 00005958 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2193                                  			; 23h user data segment, base address = 400000h ; CORE
  2194 00005960 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2195                                  			; Task State Segment
  2196 00005968 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2197                                  			       ;  no IO permission in ring 3)
  2198                                  gdt_tss0:
  2199 0000596A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2200                                  gdt_tss1:
  2201 0000596C 00                      	db 0  ; TSS base address, bits 16-23 
  2202                                  	      		; 49h	
  2203 0000596D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2204 0000596E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2205                                  gdt_tss2:
  2206 0000596F 00                      	db 0  ; TSS base address, bits 24-31 
  2207                                  
  2208                                  gdt_end:
  2209                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2210                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2211                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2212                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2213                                  
  2214                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2215                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2216                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2217                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2218                                  		; W= Writeable, A= Accessed
  2219                                  	
  2220                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2221                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2222                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2223                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2224                                  
  2225                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2226                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2227                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2228                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2229                                  	
  2230                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2231                                  
  2232                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2233                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2234                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2235                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2236                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2237                                  		; AVL= Available to programmers	
  2238                                  
  2239                                  gdtd:
  2240 00005970 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2241 00005972 [40590000]                      dd gdt			; Address of the GDT
  2242                                  
  2243                                  	; 20/08/2014
  2244                                  idtd:
  2245 00005976 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2246 00005978 [C05E0000]                      dd idt			; Address of the IDT
  2247                                  
  2248                                  Align 4
  2249                                  
  2250                                  	; 21/08/2014
  2251                                  ilist:
  2252                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2253                                  	;
  2254                                  	; Exception list
  2255                                  	; 25/08/2014	
  2256 0000597C [05080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2257 00005980 [0C080000]              	dd	exc1	
  2258 00005984 [13080000]              	dd 	exc2	
  2259 00005988 [1A080000]              	dd	exc3	
  2260 0000598C [1E080000]              	dd	exc4	
  2261 00005990 [22080000]              	dd	exc5	
  2262 00005994 [26080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2263 00005998 [2A080000]              	dd	exc7	
  2264 0000599C [2E080000]              	dd	exc8	
  2265 000059A0 [32080000]              	dd	exc9	
  2266 000059A4 [36080000]              	dd 	exc10	
  2267 000059A8 [3A080000]              	dd	exc11
  2268 000059AC [3E080000]              	dd	exc12
  2269 000059B0 [42080000]              	dd	exc13	; 0Dh, General Protection Fault
  2270 000059B4 [46080000]              	dd 	exc14	; 0Eh, Page Fault
  2271 000059B8 [4A080000]              	dd	exc15
  2272 000059BC [4E080000]              	dd	exc16
  2273 000059C0 [52080000]              	dd	exc17
  2274 000059C4 [56080000]              	dd 	exc18
  2275 000059C8 [5A080000]              	dd	exc19
  2276 000059CC [5E080000]              	dd 	exc20
  2277 000059D0 [62080000]              	dd	exc21
  2278 000059D4 [66080000]              	dd	exc22
  2279 000059D8 [6A080000]              	dd	exc23
  2280 000059DC [6E080000]              	dd 	exc24
  2281 000059E0 [72080000]              	dd	exc25
  2282 000059E4 [76080000]              	dd	exc26
  2283 000059E8 [7A080000]              	dd	exc27
  2284 000059EC [7E080000]              	dd 	exc28
  2285 000059F0 [82080000]              	dd	exc29
  2286 000059F4 [86080000]              	dd 	exc30
  2287 000059F8 [8A080000]              	dd	exc31
  2288                                  	; Interrupt list
  2289 000059FC [40060000]              	dd	timer_int	; INT 20h
  2290                                  		;dd	irq0	
  2291 00005A00 [440B0000]              	dd	keyb_int	; 27/08/2014
  2292                                  		;dd	irq1
  2293 00005A04 [5F070000]              	dd	irq2
  2294                                  		; COM2 int
  2295 00005A08 [63070000]              	dd	irq3
  2296                                  		; COM1 int
  2297 00005A0C [6E070000]              	dd	irq4
  2298 00005A10 [79070000]              	dd	irq5
  2299                                  ;DISKETTE_INT: ;06/02/2015
  2300 00005A14 [B01E0000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2301                                  		;dd	irq6
  2302                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2303                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2304 00005A18 [F50A0000]              	dd	default_irq7	; 25/02/2015
  2305                                  		;dd	irq7
  2306                                  ; Real Time Clock Interrupt
  2307 00005A1C [93090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2308                                  		;dd	irq8	; INT 28h
  2309 00005A20 [89070000]              	dd	irq9
  2310 00005A24 [8D070000]              	dd	irq10
  2311 00005A28 [91070000]              	dd	irq11
  2312 00005A2C [95070000]              	dd	irq12
  2313 00005A30 [99070000]              	dd	irq13
  2314                                  ;HDISK_INT1:  ;06/02/2015 	
  2315 00005A34 [7A230000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2316                                  		;dd	irq14
  2317                                  ;HDISK_INT2:  ;06/02/2015
  2318 00005A38 [9D230000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2319                                  		;dd	irq15	; INT 2Fh
  2320                                  		; 14/08/2015
  2321 00005A3C [D32F0000]              	dd	sysent		; INT 30h (system calls)
  2322                                  	
  2323                                  	;dd	ignore_int
  2324 00005A40 00000000                	dd	0
  2325                                  
  2326                                  ;;;
  2327                                  ;;; 11/03/2015
  2328                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2329                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KYBDATA.INC
  2330                              <1> ; Last Modification: 13/06/2022
  2331                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2332                              <1> ;
  2333                              <1> ; ///////// KEYBOARD DATA ///////////////
  2334                              <1> 
  2335                              <1> ; 11/03/2015
  2336                              <1> ; 05/12/2014
  2337                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2338                              <1> ; 03/06/86  KEYBOARD BIOS
  2339                              <1> 
  2340                              <1> ;---------------------------------------------------------------------------------
  2341                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2342                              <1> ;---------------------------------------------------------------------------------
  2343                              <1> 
  2344                              <1> ;-----	TABLES FOR ALT CASE ------------
  2345                              <1> ;-----	ALT-INPUT-TABLE 
  2346 00005A44 524F50514B          <1> K30:	db	82,79,80,81,75
  2347 00005A49 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2348                              <1> ;-----	SUPER-SHIFT-TABLE 
  2349 00005A4E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2350 00005A54 161718191E1F        <1> 	db	22,23,24,25,30,31
  2351 00005A5A 202122232425        <1> 	db	32,33,34,35,36,37
  2352 00005A60 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2353 00005A66 3132                <1> 	db	49,50
  2354                              <1> 
  2355                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2356                              <1> ;-----	KEY_TABLE 
  2357 00005A68 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2358 00005A69 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2359 00005A6E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2360                              <1> _K6L    equ     $-_K6
  2361                              <1> 
  2362                              <1> ;-----	MASK_TABLE
  2363 00005A70 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2364 00005A71 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2365 00005A76 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2366                              <1> 
  2367                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2368 00005A78 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2369 00005A7E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2370                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2371 00005A84 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2372 00005A8A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2373 00005A90 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2374 00005A96 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2375 00005A9C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2376 00005AA2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2377 00005AA8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2378 00005AAE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2379                              <1> 	;				;----- FUNCTIONS ------		
  2380 00005AB2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2381 00005AB8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2382 00005ABE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2383 00005AC4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2384 00005ACA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2385                              <1> 
  2386                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2387 00005AD0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2387 00005AD9 39302D3D0809        <1>
  2388 00005ADF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2388 00005AE8 705B5D0DFF61736466- <1>
  2388 00005AF1 67686A6B6C3B27      <1>
  2389 00005AF8 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2389 00005B01 6D2C2E2FFF2AFF20FF  <1>
  2390                              <1> ;-----	LC TABLE SCAN
  2391 00005B0A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2392 00005B0F 4041424344          <1> 	db	64,65,66,67,68
  2393 00005B14 FFFF                <1> 	db	-1,-1			; NL, SL
  2394                              <1> 
  2395                              <1> ;-----	KEYPAD TABLE
  2396 00005B16 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2397 00005B1C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2398 00005B23 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2399                              <1> 
  2400                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2401 00005B28 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2401 00005B31 28295F2B0800        <1>
  2402 00005B37 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2402 00005B40 507B7D0DFF41534446- <1>
  2402 00005B49 47484A4B4C3A22      <1>
  2403 00005B50 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2403 00005B59 4D3C3E3FFF2AFF20FF  <1>
  2404                              <1> ;-----	UC TABLE SCAN
  2405 00005B62 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2406 00005B67 595A5B5C5D          <1> 	db	89,90,91,92,93
  2407 00005B6C FFFF                <1> 	db	-1,-1			; NL, SL
  2408                              <1> 
  2409                              <1> ;-----	NUM STATE TABLE
  2410 00005B6E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2410 00005B77 3233302E            <1>
  2411                              <1> 	;
  2412 00005B7B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2413                              <1> 
  2414                              <1> Align	4
  2415                              <1> ;----------------------------------------
  2416                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2417                              <1> ;----------------------------------------
  2418 00005B80 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2419 00005B81 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2420                              <1> 				; (29h default setting for video mode 3)
  2421                              <1> 				; Mode Select register Bits
  2422                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2423                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2424                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2425                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2426                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2427                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2428                              <1> 				;   BIT 6, 7 - Not Used
  2429                              <1> 
  2430                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2431                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2432                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2433                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2434                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2435                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2436                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2437                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2438                              <1> ; Mode & 37h = Video signal OFF
  2439                              <1> 			
  2440                              <1> 
  2441                              <1> ; 26/08/2014
  2442                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2443                              <1> ; Derived from IBM "pc-at" 
  2444                              <1> ; rombios source code (06/10/1985)
  2445                              <1> ; 'dseg.inc'
  2446                              <1> 
  2447                              <1> ;---------------------------------------;
  2448                              <1> ;	SYSTEM DATA AREA		;
  2449                              <1> ;----------------------------------------
  2450 00005B82 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2451                              <1> 
  2452                              <1> ;----------------------------------------
  2453                              <1> ;	KEYBOARD DATA AREAS		;
  2454                              <1> ;----------------------------------------
  2455                              <1> 
  2456 00005B83 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2457 00005B84 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2458 00005B85 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2459 00005B86 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2460 00005B87 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2461 00005B88 [985B0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2462 00005B8C [B85B0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2463 00005B90 [985B0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2464 00005B94 [985B0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2465                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2466 00005B98 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2467                              <1> 
  2468                              <1> ; /// End Of KEYBOARD DATA ///
  2329                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2330                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2331                              <1> ; Last Modification: 11/03/2015
  2332                              <1> ;		    (Data section for 'VIDEO.INC')	
  2333                              <1> ;
  2334                              <1> ; ///////// VIDEO DATA ///////////////
  2335                              <1> 
  2336                              <1> video_params:
  2337                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2338                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2339                              <1> 	; VIDEO MODE 3
  2340 00005BB8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2341 00005BBF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2342 00005BC4 00000000            <1> 	db	0,0,0,0
  2343                              <1> 
  2344                              <1> ; /// End Of VIDEO DATA ///
  2330                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2331                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKDATA.INC
  2332                              <1> ; Last Modification: 11/07/2022
  2333                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2334                              <1> ;
  2335                              <1> ; *****************************************************************************
  2336                              <1> 
  2337                              <1> ;----------------------------------------
  2338                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2339                              <1> ;	REFERENCED BY POST & BIOS	:
  2340                              <1> ;----------------------------------------
  2341                              <1> 
  2342 00005BC8 [2B5C0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2343                              <1> 
  2344                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2345                              <1> ;----------------------------------------------------------------
  2346                              <1> ; DISK_BASE							:
  2347                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2348                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2349                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2350                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2351                              <1> ;----------------------------------------------------------------
  2352                              <1> 
  2353                              <1> ;DISK_BASE:	
  2354                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2355                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2356                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2357                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2358                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2359                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2360                              <1> ;	DB	01BH		; GAP LENGTH
  2361                              <1> ;	DB	0FFH		; DTL
  2362                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2363                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2364                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2365                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2366                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2367                              <1> 
  2368                              <1> ;----------------------------------------
  2369                              <1> ;	ROM BIOS DATA AREAS		:
  2370                              <1> ;----------------------------------------
  2371                              <1> 
  2372                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2373                              <1> 
  2374                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2375                              <1> 
  2376                              <1> ;----------------------------------------
  2377                              <1> ;	DISKETTE DATA AREAS		:
  2378                              <1> ;----------------------------------------
  2379                              <1> 
  2380                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2381                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2382                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2383                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2384                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2385                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2386                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2387                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2388                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2389                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2390                              <1> 
  2391                              <1> ;----------------------------------------
  2392                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2393                              <1> ;----------------------------------------
  2394                              <1> 
  2395                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2396                              <1> 
  2397                              <1> ;----------------------------------------
  2398                              <1> ;	TIMER DATA AREA 		:
  2399                              <1> ;----------------------------------------
  2400                              <1> 
  2401                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2402                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2403                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2404                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2405                              <1> 
  2406                              <1> ;----------------------------------------
  2407                              <1> ;	ADDITIONAL MEDIA DATA		:
  2408                              <1> ;----------------------------------------
  2409                              <1> 
  2410                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2411                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2412                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2413                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2414                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2415                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2416                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2417                              <1> 
  2418                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2419                              <1> 
  2420                              <1> ;--------------------------------------------------------
  2421                              <1> ;	DRIVE TYPE TABLE				:
  2422                              <1> ;--------------------------------------------------------
  2423                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2424                              <1> DR_TYPE:
  2425 00005BCC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2426                              <1>                 ;DW      MD_TBL1
  2427 00005BCD [EA5B0000]          <1> 		dd	MD_TBL1
  2428 00005BD1 82                  <1> 		DB	02+BIT7ON
  2429                              <1> 		;DW      MD_TBL2
  2430 00005BD2 [F75B0000]          <1>                 dd      MD_TBL2
  2431 00005BD6 02                  <1> DR_DEFAULT:	DB	02
  2432                              <1>                 ;DW      MD_TBL3
  2433 00005BD7 [045C0000]          <1> 		dd      MD_TBL3
  2434 00005BDB 03                  <1> 		DB	03
  2435                              <1>                 ;DW      MD_TBL4
  2436 00005BDC [115C0000]          <1> 		dd      MD_TBL4
  2437 00005BE0 84                  <1> 		DB	04+BIT7ON
  2438                              <1>                 ;DW      MD_TBL5
  2439 00005BE1 [1E5C0000]          <1> 		dd      MD_TBL5
  2440 00005BE5 04                  <1> 		DB	04
  2441                              <1>                 ;DW      MD_TBL6
  2442 00005BE6 [2B5C0000]          <1> 		dd      MD_TBL6
  2443                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2444                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2445                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2446                              <1> ;--------------------------------------------------------
  2447                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2448                              <1> ;--------------------------------------------------------
  2449                              <1> ;--------------------------------------------------------
  2450                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2451                              <1> ;--------------------------------------------------------
  2452                              <1> MD_TBL1:        
  2453 00005BEA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2454 00005BEB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2455 00005BEC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2456 00005BED 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2457 00005BEE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2458 00005BEF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2459 00005BF0 FF                  <1> 	DB	0FFH		; DTL
  2460 00005BF1 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2461 00005BF2 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2462 00005BF3 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2463 00005BF4 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2464 00005BF5 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2465 00005BF6 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2466                              <1> ;--------------------------------------------------------
  2467                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2468                              <1> ;--------------------------------------------------------
  2469                              <1> MD_TBL2:        
  2470 00005BF7 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2471 00005BF8 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2472 00005BF9 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2473 00005BFA 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2474 00005BFB 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2475 00005BFC 2A                  <1> 	DB	02AH		; GAP LENGTH
  2476 00005BFD FF                  <1> 	DB	0FFH		; DTL
  2477 00005BFE 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2478 00005BFF F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2479 00005C00 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2480 00005C01 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2481 00005C02 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2482 00005C03 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2483                              <1> ;--------------------------------------------------------
  2484                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2485                              <1> ;--------------------------------------------------------
  2486                              <1> MD_TBL3:
  2487 00005C04 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2488 00005C05 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2489 00005C06 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2490 00005C07 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2491 00005C08 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2492 00005C09 1B                  <1> 	DB	01BH		; GAP LENGTH
  2493 00005C0A FF                  <1> 	DB	0FFH		; DTL
  2494 00005C0B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2495 00005C0C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2496 00005C0D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2497 00005C0E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2498 00005C0F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2499 00005C10 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2500                              <1> ;--------------------------------------------------------
  2501                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2502                              <1> ;--------------------------------------------------------
  2503                              <1> MD_TBL4:
  2504 00005C11 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2505 00005C12 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2506 00005C13 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2507 00005C14 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2508 00005C15 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2509 00005C16 2A                  <1> 	DB	02AH		; GAP LENGTH
  2510 00005C17 FF                  <1> 	DB	0FFH		; DTL
  2511 00005C18 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2512 00005C19 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2513 00005C1A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2514 00005C1B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2515 00005C1C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2516 00005C1D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2517                              <1> ;--------------------------------------------------------
  2518                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2519                              <1> ;--------------------------------------------------------
  2520                              <1> MD_TBL5:
  2521 00005C1E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2522 00005C1F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2523 00005C20 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2524 00005C21 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2525 00005C22 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2526 00005C23 2A                  <1> 	DB	02AH		; GAP LENGTH
  2527 00005C24 FF                  <1> 	DB	0FFH		; DTL
  2528 00005C25 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2529 00005C26 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2530 00005C27 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2531 00005C28 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2532 00005C29 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2533 00005C2A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2534                              <1> ;--------------------------------------------------------
  2535                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2536                              <1> ;--------------------------------------------------------
  2537                              <1> MD_TBL6:
  2538 00005C2B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2539 00005C2C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2540 00005C2D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2541 00005C2E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2542 00005C2F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2543 00005C30 1B                  <1> 	DB	01BH		; GAP LENGTH
  2544 00005C31 FF                  <1> 	DB	0FFH		; DTL
  2545 00005C32 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2546 00005C33 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2547 00005C34 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2548 00005C35 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2549 00005C36 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2550 00005C37 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2551                              <1> 
  2552                              <1> 
  2553                              <1> ; << diskette.inc >>
  2554                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2555                              <1> ;
  2556                              <1> ;----------------------------------------
  2557                              <1> ;	ROM BIOS DATA AREAS		:
  2558                              <1> ;----------------------------------------
  2559                              <1> 
  2560                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2561                              <1> 
  2562                              <1> ;----------------------------------------
  2563                              <1> ;	FIXED DISK DATA AREAS		:
  2564                              <1> ;----------------------------------------
  2565                              <1> 
  2566                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2567                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2568                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2569                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2570                              <1> 
  2571                              <1> ;----------------------------------------
  2572                              <1> ;	ADDITIONAL MEDIA DATA		:
  2573                              <1> ;----------------------------------------
  2574                              <1> 
  2575                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2576                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2577                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2578                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2579                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2580                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2581                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2582                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2583                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2584                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2585                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2586                              <1> 
  2587                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2588                              <1> ;
  2589                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2590                              <1> 
  2591                              <1> ERR_TBL:
  2592 00005C38 E0                  <1> 	db	NO_ERR
  2593 00005C39 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2594 00005C3D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2595                              <1> 
  2596                              <1> ; 11/07/2022
  2597                              <1> ; 17/12/2014 (mov ax, [cfd])
  2598                              <1> ; 11/12/2014
  2599                              <1> ;cfd:		db 0			; current floppy drive (for GET_PARM)
  2600                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2601                              <1> ;pfd:		db 1			; previous floppy drive (for GET_PARM)
  2602                              <1> 					; (initial value of 'pfd 
  2603                              <1> 					; must be different then 'cfd' value
  2604                              <1> 					; to force updating/initializing
  2605                              <1> 					; current drive parameters) 
  2606                              <1> 
  2607                              <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2608 00005C41 FF                  <1> pfd:		db 0FFh
  2609                              <1> 
  2610                              <1> align 2
  2611                              <1> 
  2612 00005C42 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2613                              <1> 			      ; (170h)
  2614 00005C44 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2615                              <1> 
  2616                              <1> ; 05/01/2015 
  2617 00005C46 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2618                              <1> 
  2619                              <1> ; *****************************************************************************
  2331                                  ;;;
  2332                                  
  2333 00005C47 90                      Align 2
  2334                                  
  2335                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2336 00005C48 00                      boot_drv:    db 0 ; boot drive number (physical)
  2337                                  ; 24/11/2014
  2338 00005C49 00                      drv:	     db 0 
  2339 00005C4A 00                      last_drv:    db 0 ; last hdd
  2340 00005C4B 00                      hdc:         db 0  ; number of hard disk drives
  2341                                  		     ; (present/detected)
  2342                                  ;
  2343                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2344                                  ; Physical drive type & flags
  2345 00005C4C 00                      fd0_type:    db 0  ; floppy drive type
  2346 00005C4D 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2347                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2348                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2349                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2350                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2351 00005C4E 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2352 00005C4F 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2353 00005C50 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2354 00005C51 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2355                                  		     ; bit 0 - Fixed disk access subset supported
  2356                                  		     ; bit 1 - Drive locking and ejecting
  2357                                  		     ; bit 2 - Enhanced disk drive support
  2358                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2359                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2360                                  		     ; will interpret it as 'LBA ready'!)		
  2361                                  
  2362                                  ; 12/07/2022
  2363                                  ; (drv.cylinders, drv.spt, drv.spt will not be used now on)
  2364                                  ; ('diskio.inc')
  2365                                  ; ((spt and heads and cylinder counts will be taken from DPT))
  2366                                  
  2367                                  ; 11/03/2015 - 10/07/2015
  2368                                  ;drv.cylinders: dw 0,0,0,0,0,0,0
  2369                                  ;drv.heads:     dw 0,0,0,0,0,0,0
  2370                                  ;drv.spt:       dw 0,0,0,0,0,0,0
  2371                                  ; 12/07/2022 - 11/03/2015
  2372 00005C52 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2372 00005C5B 000000000000000000-
  2372 00005C64 000000000000000000-
  2372 00005C6D 00                 
  2373 00005C6E 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2374 00005C75 00000000000000          drv.error:     db 0,0,0,0,0,0,0
  2375                                  ;
  2376                                  
  2377                                  ; 27/08/2014
  2378                                  scr_row:
  2379 00005C7C E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2380                                  scr_col:
  2381 00005C80 00000000                	dd 0
  2382                                  
  2383                                  ;; 14/08/2015
  2384                                  ;;msgPM:
  2385                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2386                                  msgKVER:
  2387                                  	;;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0
  2388                                  	;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.3 [02/06/2022]", 0
  2389                                  	;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.4 [14/06/2022]", 0
  2390                                  	;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.5 [12/07/2022]", 0
  2391 00005C84 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.6 [24/07/2022]", 0
  2391 00005C8D 58203338362076312E-
  2391 00005C96 31202D204B65726E65-
  2391 00005C9F 6C2076302E322E312E-
  2391 00005CA8 36205B32342F30372F-
  2391 00005CB1 323032325D00       
  2392                                  
  2393 00005CB7 90                      Align 2
  2394                                  
  2395                                  ; 20/08/2014
  2396                                    ; /* This is the default interrupt "handler" :-) */ 
  2397                                    ; Linux v0.12 (head.s)
  2398                                  int_msg:
  2399 00005CB8 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2399 00005CC1 6E7465727275707420-
  2399 00005CCA 212000             
  2400                                  
  2401 00005CCD 90                      Align 2  
  2402                                  
  2403                                  ; 21/08/2014
  2404                                  timer_msg:
  2405 00005CCE 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2405 00005CD7 542032306829202120-
  2405 00005CE0 54696D657220496E74-
  2405 00005CE9 657272757074203A20 
  2406                                  tcountstr:
  2407 00005CF2 303030303020            	db "00000 "
  2408 00005CF8 00                      	db 0
  2409                                  
  2410 00005CF9 90                      Align 2
  2411                                  	; 21/08/2014
  2412                                  exc_msg:
  2413 00005CFA 435055206578636570-     	db "CPU exception ! "
  2413 00005D03 74696F6E202120     
  2414                                  excnstr: 		; 25/08/2014
  2415 00005D0A 3F3F68202045495020-     	db "??h", "  EIP : "
  2415 00005D13 3A20               
  2416                                  EIPstr: ; 29/08/2014
  2417 00005D15 00<rep Ch>              	times 12 db 0
  2418                                  rtc_msg:
  2419 00005D21 5265616C2054696D65-     	db "Real Time Clock - "
  2419 00005D2A 20436C6F636B202D20 
  2420                                  datestr:
  2421 00005D33 30302F30302F303030-     	db "00/00/0000"
  2421 00005D3C 30                 
  2422 00005D3D 20                      	db " "
  2423                                  daystr:
  2424 00005D3E 44415920                	db "DAY "
  2425                                  timestr:	
  2426 00005D42 30303A30303A3030                db "00:00:00"
  2427 00005D4A 20                      	db " "
  2428 00005D4B 00                      	db 0 
  2429                                  
  2430                                  daytmp:
  2431                                  	; 28/02/2015
  2432 00005D4C 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2432 00005D55 4F4E20545545205745-
  2432 00005D5E 442054485520465249-
  2432 00005D67 2053415420         
  2433                                  
  2434 00005D6C FF                      ptime_seconds: db 0FFh
  2435                                  
  2436                                  	; 23/02/2015
  2437                                  	; 25/08/2014
  2438                                  ;scounter:
  2439                                  ;	db 5
  2440                                  ;	db 19
  2441                                  
  2442                                  ; 02/01/2022
  2443                                  ; 05/11/2014
  2444                                  ;msg_out_of_memory:
  2445                                  ;	db 	07h, 0Dh, 0Ah
  2446                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2447                                  ; 	db	0Dh, 0Ah, 0
  2448                                  	;
  2449                                  setup_error_msg:
  2450 00005D6D 0D0A                    	db 0Dh, 0Ah
  2451 00005D6F 4469736B2053657475-     	db 'Disk Setup Error!' 
  2451 00005D78 70204572726F7221   
  2452 00005D80 0D0A00                  	db 0Dh, 0Ah,0
  2453                                  
  2454                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2455                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2456                                  ;	  db 0 ; upper left row (for scroll)	
  2457                                  
  2458                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2459                                  ;	  db 24 ; lower right row (for scroll)
  2460                                  
  2461                                  
  2462                                  ; 06/11/2014 (Temporary Data)
  2463                                  ; Memory Information message
  2464                                  ; 14/08/2015
  2465                                  msg_memory_info:
  2466 00005D83 07                      	db	07h
  2467 00005D84 0D0A                    	db	0Dh, 0Ah
  2468                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2469 00005D86 546F74616C206D656D-     	db	"Total memory : "
  2469 00005D8F 6F7279203A20       
  2470                                  mem_total_b_str: ; 10 digits
  2471 00005D95 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2471 00005D9E 302062797465730D0A 
  2472 00005DA7 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2472 00005DB0 202020202020202020 
  2473                                  mem_total_p_str: ; 7 digits
  2474 00005DB9 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2474 00005DC2 616765730D0A       
  2475 00005DC8 0D0A                    	db 	0Dh, 0Ah
  2476 00005DCA 46726565206D656D6F-     	db	"Free memory  : "
  2476 00005DD3 727920203A20       
  2477                                  free_mem_b_str:  ; 10 digits
  2478 00005DD9 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2478 00005DE2 3F2062797465730D0A 
  2479 00005DEB 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2479 00005DF4 202020202020202020 
  2480                                  free_mem_p_str:  ; 7 digits
  2481 00005DFD 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2481 00005E06 616765730D0A       
  2482 00005E0C 0D0A00                  	db	0Dh, 0Ah, 0
  2483                                  
  2484                                  dsk_ready_msg:
  2485 00005E0F 0D0A                    	db 	0Dh, 0Ah
  2486                                  dsktype:
  2487 00005E11 6664                    	db	'fd'
  2488                                  dskx:
  2489 00005E13 30                      	db	'0'
  2490 00005E14 20                      	db	20h
  2491 00005E15 697320524541445920-     	db 	'is READY ...'
  2491 00005E1E 2E2E2E             
  2492 00005E21 00                      	db 	0
  2493                                  nextline:
  2494 00005E22 0D0A00                  	db 	0Dh, 0Ah, 0
  2495                                  
  2496                                  ; KERNEL - SYSINIT Messages
  2497                                  ; 24/08/2015
  2498                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2499                                  ; 14/07/2013
  2500                                  ;kernel_init_err_msg:
  2501                                  ;	db 0Dh, 0Ah
  2502                                  ;	db 07h
  2503                                  ;	db 'Kernel initialization ERROR !'
  2504                                  ;	db 0Dh, 0Ah, 0 
  2505                                  ; 24/08/2015
  2506                                  ;;; (temporary kernel init message has been removed
  2507                                  ;;;  from 'sys_init' code)
  2508                                  ;kernel_init_ok_msg: 
  2509                                  ;	db 0Dh, 0Ah
  2510                                  ;	db 07h
  2511                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2512                                  ;	db 0Dh, 0Ah
  2513                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2514                                  ;	db 0Dh, 0Ah, 0
  2515                                  panic_msg:
  2516 00005E25 0D0A07                  	db 0Dh, 0Ah, 07h
  2517 00005E28 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2517 00005E31 726E656C2050616E69-
  2517 00005E3A 632021             
  2518 00005E3D 0D0A00                  	db 0Dh, 0Ah, 0
  2519                                  etc_init_err_msg:
  2520 00005E40 0D0A                    	db 0Dh, 0Ah
  2521 00005E42 07                      	db 07h
  2522 00005E43 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2522 00005E4C 74632F696E69742021-
  2522 00005E55 3F                 
  2523 00005E56 0D0A00                  	db 0Dh, 0Ah, 0
  2524                                  
  2525                                  ; 10/05/2015
  2526                                  badsys_msg:
  2527 00005E59 0D0A                    	db 0Dh, 0Ah
  2528 00005E5B 07                      	db 07h
  2529 00005E5C 496E76616C69642053-     	db 'Invalid System Call !'
  2529 00005E65 797374656D2043616C-
  2529 00005E6E 6C2021             
  2530 00005E71 0D0A                    	db 0Dh, 0Ah
  2531 00005E73 4541583A20              	db 'EAX: '
  2532                                  bsys_msg_eax:
  2533 00005E78 303030303030303068      	db '00000000h'
  2534 00005E81 0D0A                    	db 0Dh, 0Ah
  2535 00005E83 4549503A20              	db 'EIP: '
  2536                                  bsys_msg_eip:
  2537 00005E88 303030303030303068      	db '00000000h' 
  2538 00005E91 0D0A00                  	db 0Dh, 0Ah, 0
  2539                                  
  2540                                  BSYS_M_SIZE equ $ - badsys_msg
  2541                                  
  2542                                  
  2543                                  align 2
  2544                                  
  2545                                  ; EPOCH Variables
  2546                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2547                                  ; 09/04/2013 epoch variables
  2548                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2549                                  ;
  2550 00005E94 B207                    year: 	dw 1970
  2551                                  ;month: dw 1
  2552                                  ;day: 	dw 1
  2553                                  ;hour: 	dw 0
  2554                                  ;minute: dw 0
  2555                                  ;second: dw 0
  2556                                  ; 02/06/2022
  2557 00005E96 01                      month:	db 1
  2558 00005E97 01                      day:	db 1
  2559 00005E98 01                      hour:	db 1
  2560 00005E99 01                      minute: db 1
  2561 00005E9A 01                      second:	db 1
  2562 00005E9B 01                      	db 1
  2563                                  
  2564                                  DMonth:
  2565 00005E9C 0000                    	dw 0
  2566 00005E9E 1F00                    	dw 31
  2567 00005EA0 3B00                    	dw 59
  2568 00005EA2 5A00                    	dw 90
  2569 00005EA4 7800                    	dw 120
  2570 00005EA6 9700                    	dw 151
  2571 00005EA8 B500                    	dw 181
  2572 00005EAA D400                    	dw 212
  2573 00005EAC F300                    	dw 243
  2574 00005EAE 1101                    	dw 273
  2575 00005EB0 3001                    	dw 304
  2576 00005EB2 4E01                    	dw 334
  2577                                  
  2578                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2579                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2580 00005EB4 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2581                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2582 00005EB6 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2583 00005EB8 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2584                                  		   ;   between 16 MB and 4 GB.
  2585 00005EBA 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2586                                  
  2587                                  ; 02/01/2022
  2588                                  KEND:
  2589                                  
  2590 00005EBC 90<rep 4h>              align 16
  2591                                  
  2592                                  bss_start:
  2593                                  
  2594                                  ABSOLUTE bss_start
  2595                                  
  2596                                  	; 11/03/2015
  2597                                  	; Interrupt Descriptor Table (20/08/2014)
  2598                                  idt:
  2599 00005EC0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2600                                  idt_end:
  2601                                  
  2602                                  ;alignb 4
  2603                                  
  2604                                  task_state_segment:
  2605                                  	; 24/03/2015
  2606 000060C0 ????                    tss.link:   resw 1
  2607 000060C2 ????                    	    resw 1
  2608                                  ; tss offset 4	
  2609 000060C4 ????????                tss.esp0:   resd 1
  2610 000060C8 ????                    tss.ss0:    resw 1
  2611 000060CA ????                    	    resw 1	
  2612 000060CC ????????                tss.esp1:   resd 1
  2613 000060D0 ????                    tss.ss1:    resw 1
  2614 000060D2 ????                    	    resw 1 	
  2615 000060D4 ????????                tss.esp2:   resd 1
  2616 000060D8 ????                    tss.ss2:    resw 1
  2617 000060DA ????                    	    resw 1
  2618                                  ; tss offset 28
  2619 000060DC ????????                tss.CR3:    resd 1
  2620 000060E0 ????????                tss.eip:    resd 1
  2621 000060E4 ????????                tss.eflags: resd 1
  2622                                  ; tss offset 40
  2623 000060E8 ????????                tss.eax:    resd 1		 		
  2624 000060EC ????????                tss.ecx:    resd 1
  2625 000060F0 ????????                tss.edx:    resd 1
  2626 000060F4 ????????                tss.ebx:    resd 1
  2627 000060F8 ????????                tss.esp:    resd 1
  2628 000060FC ????????                tss.ebp:    resd 1
  2629 00006100 ????????                tss.esi:    resd 1
  2630 00006104 ????????                tss.edi:    resd 1
  2631                                  ; tss offset 72
  2632 00006108 ????                    tss.ES:     resw 1
  2633 0000610A ????                    	    resw 1	
  2634 0000610C ????                    tss.CS:	    resw 1
  2635 0000610E ????                    	    resw 1
  2636 00006110 ????                    tss.SS:	    resw 1
  2637 00006112 ????                    	    resw 1
  2638 00006114 ????                    tss.DS:	    resw 1
  2639 00006116 ????                    	    resw 1
  2640 00006118 ????                    tss.FS:	    resw 1
  2641 0000611A ????                    	    resw 1
  2642 0000611C ????                    tss.GS:	    resw 1
  2643 0000611E ????                    	    resw 1		
  2644 00006120 ????                    tss.LDTR:   resw 1
  2645 00006122 ????                    	    resw 1
  2646                                  ; tss offset 100		
  2647 00006124 ????                    	    resw 1		
  2648 00006126 ????                    tss.IOPB:   resw 1
  2649                                  ; tss offset 104 
  2650                                  tss_end:
  2651                                  
  2652 00006128 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2653                                  		  ;   (Physical address = Virtual address)	 	
  2654 0000612C ????????                memory_size: resd 1 ; memory size in pages
  2655 00006130 ????????                free_pages:  resd 1 ; number of free pages		
  2656 00006134 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2657                                  		  ;   first free page search
  2658 00006138 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2659                                  		  ;   next free page search will be
  2660                                  		  ; stopped after it. (end of M.A.T.)
  2661 0000613C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2662                                  		  ; first free page search
  2663                                  		  ;   will be started on it. (for user)
  2664 00006140 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2665                                  
  2666                                  ;;;
  2667                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2668                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2669 00006144 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2670                                  			  ; NOTE: active page only
  2671 00006146 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2672                                  active_page: 
  2673 00006156 ??                      ptty: 	     resb 1 	  ; current tty
  2674                                  ; 01/07/2015
  2675 00006157 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2676                                  ; 26/10/2015
  2677                                  ; 07/09/2014
  2678 00006158 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2679                                  
  2680                                  ; 21/08/2014
  2681 0000616C ????????                tcount:	     resd 1
  2682                                  
  2683                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2684 00006170 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2685                                  
  2686                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2687                                  ; (open mode locks for pseudo TTYs)
  2688                                  ; [ major tty locks (return error in any conflicts) ]
  2689 00006174 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2690                                  
  2691                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2692                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2693 00006188 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2694                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2695                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2696                                  ;; 0 means serial port is not available 
  2697                                  ;;comprm: ; 25/06/2014
  2698 00006192 ??                      com1p:       resb 1  ;;0E3h
  2699 00006193 ??                      com2p:       resb 1  ;;0E3h
  2700                                  
  2701                                  ; 17/11/2015
  2702                                  ; request for response (from the terminal)	
  2703 00006194 ????                    req_resp:     resw 1 			
  2704                                  ; 07/11/2015
  2705 00006196 ??                      ccomport:    resb 1 ; current COM (serial) port
  2706                                  		    ; (0= COM1, 1= COM2)
  2707                                  ; 09/11/2015
  2708 00006197 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2709                                  ; 07/11/2015
  2710 00006198 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2711 0000619A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2712                                  
  2713                                  ; 23/10/2015
  2714                                  ; SERIAL PORTS - COMMUNICATION MODES
  2715                                  ; (Retro UNIX 386 v1 feature only!)
  2716                                  ; 0 - command mode (default/initial mode)
  2717                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2718                                  ;;; communication modes for futre versions:  
  2719                                  ; // 2 - keyboard mode (ascii+scancode input)
  2720                                  ; // 3 - mouse mode
  2721                                  ; // 4 - device control (output) mode
  2722                                  ; VALID COMMANDS for current version:
  2723                                  ; 	'LOGIN'
  2724                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2725                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2726                                  ;  Login response: db 0FFh, 'login', 0
  2727                                  ;	 ("login request accepted, wait for login prompt") 
  2728                                  ; When a login requests is received and acknowledged (by
  2729                                  ; serial port interrupt handler (communication procedure),
  2730                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2731                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2732                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2733                                  ; 
  2734                                  ; 'sys connect' system call is used to change communication mode
  2735                                  ; except 'LOGIN' command which is used to start terminal mode
  2736                                  ; by using (COM port) terminal.
  2737                                  
  2738                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2739                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2740                                  ;com1mode:    resb 1 ; communication mode for COM1
  2741                                  ;com1com:     resb 1 ; communication command for COM1
  2742                                  ;com2mode:    resb 1 ; communication mode for COM1
  2743                                  ;com2com      resb 1 ; communication command for COM1
  2744                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2745                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2746                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2747                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2748                                  
  2749                                  ; 22/08/2014 (RTC)
  2750                                  ; (Packed BCD)
  2751 0000619C ??                      time_seconds: resb 1
  2752 0000619D ??                      time_minutes: resb 1
  2753 0000619E ??                      time_hours:   resb 1
  2754 0000619F ??                      date_wday:    resb 1
  2755 000061A0 ??                      date_day:     resb 1
  2756 000061A1 ??                      date_month:   resb 1			
  2757 000061A2 ??                      date_year:    resb 1
  2758 000061A3 ??                      date_century: resb 1
  2759                                  
  2760                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2761                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKBSS.INC
  2762                              <1> ; Last Modification: 10/07/2022
  2763                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC') 
  2764                              <1> ;
  2765                              <1> ; *****************************************************************************
  2766                              <1> 
  2767                              <1> alignb 2
  2768                              <1> 
  2769                              <1> ;----------------------------------------
  2770                              <1> ;	TIMER DATA AREA 		:
  2771                              <1> ;----------------------------------------
  2772                              <1> 
  2773                              <1> TIMER_LH:	; 16/02/205
  2774 000061A4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2775 000061A6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2776 000061A8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2777                              <1> 
  2778                              <1> ;----------------------------------------
  2779                              <1> ;	DISKETTE DATA AREAS		:
  2780                              <1> ;----------------------------------------
  2781                              <1> 
  2782 000061A9 ??                  <1> SEEK_STATUS:	resb	1
  2783 000061AA ??                  <1> MOTOR_STATUS:	resb	1
  2784 000061AB ??                  <1> MOTOR_COUNT:	resb	1
  2785 000061AC ??                  <1> DSKETTE_STATUS:	resb	1
  2786 000061AD ??????????????      <1> NEC_STATUS:	resb	7
  2787                              <1> 
  2788                              <1> ;----------------------------------------
  2789                              <1> ;	ADDITIONAL MEDIA DATA		:
  2790                              <1> ;----------------------------------------
  2791                              <1> 
  2792 000061B4 ??                  <1> LASTRATE:	resb 	1
  2793 000061B5 ??                  <1> HF_STATUS:	resb 	1
  2794                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2795 000061B6 ??                  <1> HF_INT_FLAG:	resb	1
  2796                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2797                              <1> ;DSK_STATE:	resb 	4
  2798 000061B7 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2799 000061B9 ????                <1> DSK_TRK:	resb 	2
  2800                              <1> 
  2801                              <1> ;----------------------------------------
  2802                              <1> ;	FIXED DISK DATA AREAS		:
  2803                              <1> ;----------------------------------------
  2804                              <1> 
  2805 000061BB ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2806 000061BC ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2807 000061BD ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2808                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2809                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2810                              <1> ;port2_off	resb	1		; Hard disk controller 2 - port offset
  2811                              <1> 
  2812 000061BE ????                <1> alignb 4
  2813                              <1> 
  2814                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2815                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2816                              <1> HF_TBL_VEC: ; 22/12/2014	
  2817 000061C0 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2818 000061C4 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2819 000061C8 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2820 000061CC ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2821                              <1> 
  2822                              <1> ; 03/01/2015
  2823 000061D0 ??                  <1> LBAMode:     	resb	1
  2824                              <1> 
  2825                              <1> ; *****************************************************************************
  2761                                  
  2762                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2763                                  
  2764                                  ;alignb 2
  2765                                  
  2766                                  ; 02/01/2022
  2767                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2768                                  
  2769                                  ; 24/12/2021
  2770                                  ; (memory page swap parameters are disabled as temporary)
  2771                                  ;
  2772                                  ;; Memory (swap) Data (11/03/2015)
  2773                                  ; 09/03/2015
  2774                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2775                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2776                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2777                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2778                                  ;swpd_next:  resd 1 ; next free page block
  2779                                  ;swpd_last:  resd 1 ; last swap page block	
  2780                                  	
  2781 000061D1 ??????                  alignb 4
  2782                                  
  2783                                  ; 10/07/2015
  2784                                  ; 28/08/2014
  2785 000061D4 ????????                error_code:	resd 1
  2786                                  ; 29/08/2014
  2787 000061D8 ????????                FaultOffset: 	resd 1
  2788                                  ; 21/09/2015
  2789 000061DC ????????                PF_Count:	resd 1	; total page fault count
  2790                                  		       	; (for debugging - page fault analyze)
  2791                                  		 	; 'page _fault_handler' (memory.inc)
  2792                                  			; 'sysgeterr' (u9.s)
  2793                                  ; 26/02/2022
  2794 000061E0 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2795                                  			;  for a system call in next retro unix 386 version)
  2796                                  			; -2 ticks per second-
  2797                                  ;; 21/08/2015
  2798                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2799                                  
  2800                                  ; 02/01/2022
  2801                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2802                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYSX.INC (ux.s)
  2803                              <1> ; Last Modification: 15/07/2022
  2804                              <1> ; ----------------------------------------------------------------------------
  2805                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2806                              <1> ; (Modified from 
  2807                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2808                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2809                              <1> ; ----------------------------------------------------------------------------
  2810                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2811                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2812                              <1> ; <Bell Laboratories (17/3/1972)>
  2813                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2814                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2815                              <1> ; ****************************************************************************
  2816                              <1> ; 04/12/2015
  2817                              <1> 
  2818                              <1> alignb 2
  2819                              <1> 
  2820                              <1> inode:
  2821                              <1> 	; 11/03/2013. 
  2822                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2823                              <1> 	;i.
  2824                              <1> 
  2825 000061E4 ????                <1> 	i.flgs:	 resw 1
  2826 000061E6 ??                  <1> 	i.nlks:	 resb 1
  2827 000061E7 ??                  <1> 	i.uid:	 resb 1
  2828 000061E8 ????                <1>         i.size:  resw 1 ; size
  2829 000061EA <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2830 000061FA ????????            <1> 	i.ctim:	 resd 1
  2831 000061FE ????????            <1> 	i.mtim:	 resd 1
  2832 00006202 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2833                              <1> 
  2834                              <1> I_SIZE	equ $ - inode 
  2835                              <1> 
  2836                              <1> process:
  2837                              <1> 	; 26/02/2022
  2838                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2839                              <1> 	; 06/05/2015
  2840                              <1> 	; 11/03/2013 - 05/02/2014
  2841                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2842                              <1> 	;p.
  2843                              <1> 	
  2844 00006204 <res 20h>           <1>         p.pid:   resw nproc
  2845 00006224 <res 20h>           <1>         p.ppid:  resw nproc
  2846                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2847 00006244 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2848                              <1> 	; 26/02/2022 (p.waitc is not used)
  2849                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2850 00006254 <res 10h>           <1> 	p.link:	 resb nproc
  2851 00006264 <res 10h>           <1> 	p.stat:	 resb nproc
  2852                              <1> 
  2853                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2854 00006274 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2855                              <1> 			    ; 'user' structure	
  2856                              <1> 
  2857                              <1> P_SIZE	equ $ - process
  2858                              <1> 
  2859                              <1> ; fsp table (original UNIX v1)
  2860                              <1> ;
  2861                              <1> ;Entry
  2862                              <1> ;          15                                      0
  2863                              <1> ;  1     |---|---------------------------------------|
  2864                              <1> ;        |r/w|       i-number of open file           |
  2865                              <1> ;        |---|---------------------------------------| 
  2866                              <1> ;        |               device number               |
  2867                              <1> ;        |-------------------------------------------|
  2868                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2869                              <1> ;        |-------------------------------------------| 
  2870                              <1> ;        |  flag that says    | number of processes  |
  2871                              <1> ;        |   file deleted     | that have file open  |
  2872                              <1> ;        |-------------------------------------------| 
  2873                              <1> ;  2     |                                           |
  2874                              <1> ;        |-------------------------------------------| 
  2875                              <1> ;        |                                           |
  2876                              <1> ;        |-------------------------------------------|
  2877                              <1> ;        |                                           |
  2878                              <1> ;        |-------------------------------------------|
  2879                              <1> ;        |                                           |
  2880                              <1> ;        |-------------------------------------------| 
  2881                              <1> ;  3     |                                           | 
  2882                              <1> ;        |                                           |  
  2883                              <1> ;
  2884                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2885                              <1> 
  2886                              <1> ; 15/04/2015
  2887 000062B4 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2888 000064A8 <res 28h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2889 000064D0 ????                <1> ii:	 resw 1
  2890                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2891                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2892                              <1> ; 11/01/2022
  2893 000064D2 ??                  <1> idev:	 resb 1
  2894 000064D3 ??                  <1> cdev:	 resb 1
  2895                              <1> ; 18/05/2015
  2896                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2897                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2898                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2899                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2900                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2901                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2902                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2903                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2904                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2905                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2906                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2907 000064D4 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2908                              <1> 	        ; as above, for physical drives numbers in following table
  2909 000064D5 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2910                              <1> ; 15/04/2015
  2911                              <1> ;active: resb 1 ; 15/07/2022
  2912                              <1> ;	 resb 1 ; 09/06/2015
  2913 000064D6 ????                <1> mnti:	 resw 1
  2914 000064D8 ????                <1> mntp:	 resw 1 ; 15/05/2022 ; (parent dir inumber of [mnti])
  2915 000064DA ????                <1> mpid:	 resw 1
  2916 000064DC ????                <1> rootdir: resw 1
  2917                              <1> ; 14/02/2014
  2918                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2919                              <1> ;		      Single level run queue
  2920                              <1> ;		      (in order to solve sleep/wakeup lock)
  2921 000064DE ????                <1> runq:	 resw 1
  2922 000064E0 ??                  <1> imod:	 resb 1
  2923 000064E1 ??                  <1> smod:	 resb 1
  2924 000064E2 ??                  <1> mmod:	 resb 1
  2925 000064E3 ??                  <1> sysflg:	 resb 1
  2926                              <1> 
  2927                              <1> alignb 4
  2928                              <1> 
  2929                              <1> user:
  2930                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2931                              <1> 	; 04/12/2015 
  2932                              <1> 	; 18/10/2015
  2933                              <1> 	; 12/10/2015
  2934                              <1> 	; 21/09/2015
  2935                              <1> 	; 24/07/2015
  2936                              <1> 	; 16/06/2015
  2937                              <1> 	; 09/06/2015
  2938                              <1> 	; 11/05/2015
  2939                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2940                              <1> 	; 10/10/2013
  2941                              <1> 	; 11/03/2013. 
  2942                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2943                              <1> 	;u.
  2944                              <1> 
  2945 000064E4 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2946 000064E8 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2947 000064EC ????????            <1> 	u.r0:	  resd 1 ; eax
  2948 000064F0 ????                <1> 	u.cdir:	  resw 1
  2949 000064F2 <res Ah>            <1> 	u.fp:	  resb 10
  2950 000064FC ????????            <1> 	u.fofp:	  resd 1
  2951 00006500 ????????            <1> 	u.dirp:	  resd 1
  2952 00006504 ????????            <1> 	u.namep:  resd 1
  2953 00006508 ????????            <1> 	u.off:	  resd 1
  2954 0000650C ????????            <1> 	u.base:	  resd 1
  2955 00006510 ????????            <1> 	u.count:  resd 1
  2956 00006514 ????????            <1> 	u.nread:  resd 1
  2957 00006518 ????????            <1> 	u.break:  resd 1 ; break
  2958 0000651C ????                <1> 	u.ttyp:	  resw 1 
  2959 0000651E <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2960                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2961 0000652E ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2962 0000652F ??                  <1> 	u.pri:	  resb 1 ; 
  2963 00006530 ????                <1> 	u.intr:	  resw 1
  2964 00006532 ????                <1> 	u.quit:	  resw 1
  2965                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2966 00006534 ????                <1> 	u.ilgins: resw 1
  2967                              <1> 	;u.cdrv:  resw 1 ; cdev
  2968 00006536 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2969 00006537 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2970 00006538 ??                  <1> 	u.uid:	  resb 1 ; uid
  2971 00006539 ??                  <1> 	u.ruid:	  resb 1
  2972 0000653A ??                  <1> 	u.bsys:	  resb 1
  2973 0000653B ??                  <1> 	u.uno:	  resb 1
  2974 0000653C ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2975                              <1> 	; tty number (rtty, rcvt, wtty)
  2976 00006540 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2977                              <1> 	; last error number
  2978 00006541 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2979                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2980 00006545 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2981 00006549 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2982 0000654D ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2983 00006551 ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2984                              <1> 	;u.pncount: resw 1 
  2985                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2986                              <1> 	;u.pnbase:  resd 1 
  2987                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2988                              <1> 			 ; 09/06/2015
  2989 00006553 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2990 00006554 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2991                              <1> 			 ; 24/07/2015 - 24/06/2015
  2992                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2993                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2994                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2995                              <1>  			 ; 24/06/2015	  	
  2996                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2997                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2998                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2999 00006555 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  3000                              <1> 
  3001 00006559 ??????              <1> alignb 4
  3002                              <1> 
  3003                              <1> U_SIZE	equ $ - user
  3004                              <1> 
  3005                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3006 0000655C ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3007 00006560 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3008 00006564 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3009 00006568 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  3010                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3011 0000656A ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3012 0000656B ??                  <1> 	resb 1 
  3013 0000656C ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3014                              <1> 
  3015                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3016                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3017 00006570 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3018 00006571 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3019 00006572 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3020 00006573 ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  3021                              <1> 
  3022                              <1> ;alignb 4
  3023                              <1> 
  3024                              <1> ; 22/08/2015
  3025 00006574 <res 1040h>         <1> buffer: resb nbuf * 520
  3026                              <1> 
  3027 000075B4 ????????????????    <1> sb0:	resd 2
  3028                              <1> ;s:
  3029                              <1> ; (root disk) super block buffer
  3030                              <1> systm:
  3031                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3032                              <1> 	; 11/03/2013. 
  3033                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3034                              <1> 	;s.
  3035                              <1> 
  3036 000075BC ????                <1> 	resw 1
  3037 000075BE <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3038 00007726 ????                <1> 	resw 1
  3039 00007728 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  3040                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  3041 00007748 ????????            <1> 	s.time:	 resd 1
  3042 0000774C ????????            <1> 	s.syst:	 resd 1
  3043 00007750 ????????            <1>         s.wait_: resd 1 ; wait
  3044 00007754 ????????            <1> 	s.idlet: resd 1
  3045 00007758 ????????            <1> 	s.chrgt: resd 1
  3046 0000775C ????                <1> 	s.drerr: resw 1
  3047                              <1> 
  3048                              <1> S_SIZE	equ $ - systm
  3049                              <1> 
  3050 0000775E <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3051                              <1> 
  3052 000077BC ????????????????    <1> sb1:	resd 2
  3053                              <1> ; (mounted disk) super block buffer
  3054                              <1> mount:	
  3055 000077C4 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3056                              <1> 
  3057                              <1> ;/ ux -- unix
  3058                              <1> ;
  3059                              <1> ;systm:
  3060                              <1> ;
  3061                              <1> ;	.=.+2
  3062                              <1> ;	.=.+128.
  3063                              <1> ;	.=.+2
  3064                              <1> ;	.=.+64.
  3065                              <1> ;	s.time: .=.+4
  3066                              <1> ;	s.syst: .=.+4
  3067                              <1> ;	s.wait: .=.+4
  3068                              <1> ;	s.idlet:.=.+4
  3069                              <1> ;	s.chrgt:.=.+4
  3070                              <1> ;	s.drerr:.=.+2
  3071                              <1> ;inode:
  3072                              <1> ;	i.flgs: .=.+2
  3073                              <1> ;	i.nlks: .=.+1
  3074                              <1> ;	i.uid:  .=.+1
  3075                              <1> ;	i.size: .=.+2
  3076                              <1> ;	i.dskp: .=.+16.
  3077                              <1> ;	i.ctim: .=.+4
  3078                              <1> ;	i.mtim: .=.+4
  3079                              <1> ;	. = inode+32.
  3080                              <1> ;mount:	.=.+1024.
  3081                              <1> ;proc:
  3082                              <1> ;	p.pid:  .=.+[2*nproc]
  3083                              <1> ;	p.dska: .=.+[2*nproc]
  3084                              <1> ;	p.ppid: .=.+[2*nproc]
  3085                              <1> ;	p.break:.=.+[2*nproc]
  3086                              <1> ;	p.link: .=.+nproc
  3087                              <1> ;	p.stat: .=.+nproc
  3088                              <1> ;tty:
  3089                              <1> ;	. = .+[ntty*8.]
  3090                              <1> ;fsp:	.=.+[nfiles*8.]
  3091                              <1> ;bufp:	.=.+[nbuf*2]+6
  3092                              <1> ;sb0:	.=.+8
  3093                              <1> ;sb1:	.=.+8
  3094                              <1> ;swp:	.=.+8
  3095                              <1> ;ii:	.=.+2
  3096                              <1> ;idev:	.=.+2
  3097                              <1> ;cdev:	.=.+2
  3098                              <1> ;deverr: .=.+12.
  3099                              <1> ;active: .=.+2
  3100                              <1> ;rfap:	.=.+2
  3101                              <1> ;rkap:	.=.+2
  3102                              <1> ;tcap:	.=.+2
  3103                              <1> ;tcstate:.=.+2
  3104                              <1> ;tcerrc: .=.+2
  3105                              <1> ;mnti:	.=.+2
  3106                              <1> ;mntd:	.=.+2
  3107                              <1> ;mpid:	.=.+2
  3108                              <1> ;clockp: .=.+2
  3109                              <1> ;rootdir:.=.+2
  3110                              <1> ;toutt:	.=.+16.
  3111                              <1> ;touts: .=.+32.
  3112                              <1> ;runq:	.=.+6
  3113                              <1> ;
  3114                              <1> ;wlist:	.=.+40.
  3115                              <1> ;cc:	.=.+30.
  3116                              <1> ;cf:	.=.+31.
  3117                              <1> ;cl:	.=.+31.
  3118                              <1> ;clist:	.=.+510.
  3119                              <1> ;imod:	.=.+1
  3120                              <1> ;smod:	.=.+1
  3121                              <1> ;mmod:	.=.+1
  3122                              <1> ;uquant: .=.+1
  3123                              <1> ;sysflg: .=.+1
  3124                              <1> ;pptiflg:.=.+1
  3125                              <1> ;ttyoch: .=.+1
  3126                              <1> ; .even
  3127                              <1> ; .=.+100.; sstack:
  3128                              <1> ;buffer: .=.+[ntty*140.]
  3129                              <1> ;	.=.+[nbuf*520.]
  3130                              <1> ;
  3131                              <1> ; . = core-64.
  3132                              <1> ;user:
  3133                              <1> ;	u.sp:    .=.+2
  3134                              <1> ;	u.usp:   .=.+2
  3135                              <1> ;	u.r0:    .=.+2
  3136                              <1> ;	u.cdir:  .=.+2
  3137                              <1> ;	u.fp:    .=.+10.
  3138                              <1> ;	u.fofp:  .=.+2
  3139                              <1> ;	u.dirp:  .=.+2
  3140                              <1> ;	u.namep: .=.+2
  3141                              <1> ;	u.off:   .=.+2
  3142                              <1> ;	u.base:  .=.+2
  3143                              <1> ;	u.count: .=.+2
  3144                              <1> ;	u.nread: .=.+2
  3145                              <1> ;	u.break: .=.+2
  3146                              <1> ;	u.ttyp:  .=.+2
  3147                              <1> ;	u.dirbuf:.=.+10.
  3148                              <1> ;	u.pri:   .=.+2
  3149                              <1> ;	u.intr:  .=.+2
  3150                              <1> ;	u.quit:  .=.+2
  3151                              <1> ;	u.emt:   .=.+2
  3152                              <1> ;	u.ilgins:.=.+2
  3153                              <1> ;	u.cdev:  .=.+2
  3154                              <1> ;	u.uid:   .=.+1
  3155                              <1> ;	u.ruid:  .=.+1
  3156                              <1> ;	u.bsys:  .=.+1
  3157                              <1> ;	u.uno:   .=.+1
  3158                              <1> ;. = core
  2802                                  
  2803                                  ; 27/12/2021
  2804                                  ;buffer: resb (nbuf*520)
  2805                                  
  2806                                  bss_end:
  2807                                  
  2808                                  ; 02/01/2022
  2809                                  BSS_SIZE equ bss_end - bss_start
  2810                                  
  2811                                  ; 27/12/2013
  2812                                  _end:  ; end of kernel code (and read only data, just before bss)
